envoc-form 5.0.3 → 5.0.5

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 (113) hide show
  1. package/README.md +158 -15
  2. package/es/Input/CheckboxGroup.d.ts +6 -0
  3. package/es/Input/CheckboxGroup.js +14 -0
  4. package/es/Input/CheckboxInputGroup.d.ts +13 -0
  5. package/es/Input/CheckboxInputGroup.js +41 -0
  6. package/es/index.d.ts +2 -0
  7. package/es/index.js +1 -0
  8. package/lib/Input/CheckboxGroup.d.ts +6 -0
  9. package/lib/Input/CheckboxGroup.js +20 -0
  10. package/lib/Input/CheckboxInputGroup.d.ts +13 -0
  11. package/lib/Input/CheckboxInputGroup.js +46 -0
  12. package/lib/index.d.ts +2 -0
  13. package/lib/index.js +3 -1
  14. package/package.json +111 -111
  15. package/src/AddressInput/AddressInput.test.tsx +27 -27
  16. package/src/AddressInput/AddressInput.tsx +82 -82
  17. package/src/AddressInput/UsStates.ts +55 -55
  18. package/src/AddressInput/__snapshots__/AddressInput.test.tsx.snap +182 -182
  19. package/src/ConfirmBaseForm/ConfirmBaseForm.test.tsx +24 -24
  20. package/src/ConfirmBaseForm/ConfirmBaseForm.tsx +74 -74
  21. package/src/ConfirmBaseForm/__snapshots__/ConfirmBaseForm.test.tsx.snap +23 -23
  22. package/src/ConfirmDeleteForm/ConfirmDeleteForm.test.tsx +24 -24
  23. package/src/ConfirmDeleteForm/ConfirmDeleteForm.tsx +87 -87
  24. package/src/ConfirmDeleteForm/__snapshots__/ConfirmDeleteForm.test.tsx.snap +25 -25
  25. package/src/DatePicker/DatePicker.test.tsx +48 -48
  26. package/src/DatePicker/DatePickerGroup.tsx +115 -115
  27. package/src/DatePicker/DatePickerHelper.ts +4 -4
  28. package/src/DatePicker/StringDateOnlyPickerGroup.tsx +28 -28
  29. package/src/DatePicker/StringDatePickerGroup.tsx +20 -20
  30. package/src/DatePicker/__snapshots__/DatePicker.test.tsx.snap +152 -152
  31. package/src/Field/CustomFieldInputProps.ts +10 -10
  32. package/src/Field/CustomFieldMetaProps.ts +5 -5
  33. package/src/Field/Field.tsx +113 -113
  34. package/src/Field/FieldErrorScrollTarget.tsx +12 -12
  35. package/src/Field/FieldNameContext.ts +6 -6
  36. package/src/Field/FieldSection.tsx +18 -18
  37. package/src/Field/InjectedFieldProps.ts +8 -8
  38. package/src/Field/StandAloneInput.tsx +55 -55
  39. package/src/Field/useStandardField.ts +125 -125
  40. package/src/FieldArray/FieldArray.tsx +154 -154
  41. package/src/File/FileGroup.test.tsx +35 -35
  42. package/src/File/FileGroup.tsx +85 -85
  43. package/src/File/FileList.tsx +21 -21
  44. package/src/File/__snapshots__/FileGroup.test.tsx.snap +34 -34
  45. package/src/File/humanFileSize.ts +8 -8
  46. package/src/Form/FocusError.tsx +55 -55
  47. package/src/Form/Form.test.tsx +14 -14
  48. package/src/Form/Form.tsx +237 -237
  49. package/src/Form/FormBasedPreventNavigation.tsx +56 -56
  50. package/src/Form/LegacyFormBasedPreventNavigation.tsx +77 -77
  51. package/src/Form/NewFormBasedPreventNavigation.tsx +59 -59
  52. package/src/Form/ServerErrorContext.ts +18 -18
  53. package/src/Form/__snapshots__/Form.test.tsx.snap +10 -10
  54. package/src/FormActions.tsx +47 -47
  55. package/src/FormDefaults.ts +2 -2
  56. package/src/Group.tsx +62 -62
  57. package/src/Input/CheckboxGroup.tsx +60 -0
  58. package/src/Input/CheckboxInputGroup.tsx +78 -0
  59. package/src/Input/IconInputGroup.tsx +54 -54
  60. package/src/Input/InputGroup.tsx +72 -72
  61. package/src/Input/MoneyInputGroup.tsx +50 -50
  62. package/src/Input/NumberInputGroup.tsx +48 -48
  63. package/src/Input/PhoneNumberInputGroup.tsx +45 -45
  64. package/src/Input/StringInputGroup.tsx +53 -53
  65. package/src/Input/__Tests__/CheckboxInputGroup.test.tsx +26 -0
  66. package/src/Input/__Tests__/IconInputGroup.test.tsx +35 -35
  67. package/src/Input/__Tests__/MoneyInputGroup.test.tsx +37 -37
  68. package/src/Input/__Tests__/NumberInputGroup.test.tsx +35 -35
  69. package/src/Input/__Tests__/PhoneNumberInputGroup.test.tsx +36 -36
  70. package/src/Input/__Tests__/StringInputGroup.test.tsx +27 -27
  71. package/src/Input/__Tests__/__snapshots__/CheckboxInputGroup.test.tsx.snap +33 -0
  72. package/src/Input/__Tests__/__snapshots__/IconInputGroup.test.tsx.snap +32 -32
  73. package/src/Input/__Tests__/__snapshots__/MoneyInputGroup.test.tsx.snap +34 -34
  74. package/src/Input/__Tests__/__snapshots__/NumberInputGroup.test.tsx.snap +32 -32
  75. package/src/Input/__Tests__/__snapshots__/PhoneNumberInputGroup.test.tsx.snap +33 -33
  76. package/src/Input/__Tests__/__snapshots__/StringInputGroup.test.tsx.snap +31 -31
  77. package/src/Normalization/NormalizationFunction.ts +4 -4
  78. package/src/Normalization/normalizers.ts +44 -44
  79. package/src/Select/BooleanSelectGroup.tsx +28 -28
  80. package/src/Select/NumberSelectGroup.tsx +16 -16
  81. package/src/Select/SelectGroup.tsx +124 -124
  82. package/src/Select/SelectGroupPropsHelper.ts +4 -4
  83. package/src/Select/StringSelectGroup.tsx +16 -16
  84. package/src/Select/__tests__/BooleanSelectGroup.test.tsx +35 -35
  85. package/src/Select/__tests__/NumberSelectGroup.test.tsx +87 -87
  86. package/src/Select/__tests__/StringSelectGroup.test.tsx +89 -89
  87. package/src/Select/__tests__/__snapshots__/BooleanSelectGroup.test.tsx.snap +98 -98
  88. package/src/Select/__tests__/__snapshots__/NumberSelectGroup.test.tsx.snap +195 -195
  89. package/src/Select/__tests__/__snapshots__/StringSelectGroup.test.tsx.snap +195 -195
  90. package/src/StandardFormActions.tsx +41 -41
  91. package/src/SubmitFormButton.tsx +54 -54
  92. package/src/TextArea/TextAreaGroup.tsx +64 -64
  93. package/src/Validation/ValidatedApiResult.ts +8 -8
  94. package/src/Validation/ValidationError.ts +6 -6
  95. package/src/Validation/ValidationFunction.ts +4 -4
  96. package/src/Validation/validators.test.tsx +81 -81
  97. package/src/Validation/validators.ts +97 -97
  98. package/src/__Tests__/FormTestBase.tsx +65 -64
  99. package/src/__Tests__/RealisticForm.test.tsx +82 -82
  100. package/src/__Tests__/StandardFormActions.test.tsx +17 -17
  101. package/src/__Tests__/SubmitFormButton.test.tsx +17 -17
  102. package/src/__Tests__/__snapshots__/StandardFormActions.test.tsx.snap +27 -27
  103. package/src/__Tests__/__snapshots__/SubmitFormButton.test.tsx.snap +20 -20
  104. package/src/__Tests__/index.ts +3 -3
  105. package/src/_variables.scss +11 -11
  106. package/src/index.ts +156 -153
  107. package/src/react-app-env.d.ts +1 -1
  108. package/src/setupTests.ts +1 -1
  109. package/src/utils/objectContainsNonSerializableProperty.test.tsx +49 -49
  110. package/src/utils/objectContainsNonSerializableProperty.ts +17 -17
  111. package/src/utils/objectToFormData.test.tsx +76 -76
  112. package/src/utils/objectToFormData.ts +105 -105
  113. package/src/utils/typeChecks.ts +18 -18
@@ -1,152 +1,152 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`IconInputGroup has matching snapshot 1`] = `
4
- <DocumentFragment>
5
- <form
6
- action="#"
7
- class="envoc-form-form"
8
- >
9
- <div
10
- class="envoc-form-date-picker envoc-form-group"
11
- >
12
- <div
13
- id="favoritedate-error-scroll-target"
14
- style="display: none;"
15
- />
16
- <label
17
- for="favoriteDate"
18
- >
19
- Favorite Date
20
- </label>
21
- <div
22
- class="react-date-picker react-date-picker--closed react-date-picker--enabled envoc-form-date-picker"
23
- >
24
- <div
25
- class="react-date-picker__wrapper"
26
- >
27
- <div
28
- class="react-date-picker__inputGroup"
29
- >
30
- <input
31
- max="2023-09-23"
32
- min="2022-06-22"
33
- name="date"
34
- style="visibility: hidden; position: absolute; z-index: -999;"
35
- type="date"
36
- value=""
37
- />
38
- <input
39
- autocomplete="off"
40
- class="react-date-picker__inputGroup__input react-date-picker__inputGroup__month"
41
- data-input="true"
42
- inputmode="numeric"
43
- max="12"
44
- min="1"
45
- name="month"
46
- placeholder="mm"
47
- type="number"
48
- value=""
49
- />
50
- <span
51
- class="react-date-picker__inputGroup__divider"
52
- >
53
- /
54
- </span>
55
- <input
56
- autocomplete="off"
57
- class="react-date-picker__inputGroup__input react-date-picker__inputGroup__day"
58
- data-input="true"
59
- inputmode="numeric"
60
- max="31"
61
- min="1"
62
- name="day"
63
- placeholder="dd"
64
- type="number"
65
- value=""
66
- />
67
- <span
68
- class="react-date-picker__inputGroup__divider"
69
- >
70
- /
71
- </span>
72
- <input
73
- autocomplete="off"
74
- class="react-date-picker__inputGroup__input react-date-picker__inputGroup__year"
75
- data-input="true"
76
- inputmode="numeric"
77
- max="2023"
78
- min="2022"
79
- name="year"
80
- placeholder="yyyy"
81
- step="1"
82
- type="number"
83
- value=""
84
- />
85
- </div>
86
- <button
87
- class="react-date-picker__clear-button react-date-picker__button"
88
- type="button"
89
- >
90
- <svg
91
- class="react-date-picker__clear-button__icon react-date-picker__button__icon"
92
- height="19"
93
- stroke="black"
94
- stroke-width="2"
95
- viewBox="0 0 19 19"
96
- width="19"
97
- xmlns="http://www.w3.org/2000/svg"
98
- >
99
- <line
100
- x1="4"
101
- x2="15"
102
- y1="4"
103
- y2="15"
104
- />
105
- <line
106
- x1="15"
107
- x2="4"
108
- y1="4"
109
- y2="15"
110
- />
111
- </svg>
112
- </button>
113
- <button
114
- class="react-date-picker__calendar-button react-date-picker__button"
115
- type="button"
116
- >
117
- <svg
118
- class="react-date-picker__calendar-button__icon react-date-picker__button__icon"
119
- height="19"
120
- stroke="black"
121
- stroke-width="2"
122
- viewBox="0 0 19 19"
123
- width="19"
124
- xmlns="http://www.w3.org/2000/svg"
125
- >
126
- <rect
127
- fill="none"
128
- height="15"
129
- width="15"
130
- x="2"
131
- y="2"
132
- />
133
- <line
134
- x1="6"
135
- x2="6"
136
- y1="0"
137
- y2="4"
138
- />
139
- <line
140
- x1="13"
141
- x2="13"
142
- y1="0"
143
- y2="4"
144
- />
145
- </svg>
146
- </button>
147
- </div>
148
- </div>
149
- </div>
150
- </form>
151
- </DocumentFragment>
152
- `;
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`IconInputGroup has matching snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <form
6
+ action="#"
7
+ class="envoc-form-form"
8
+ >
9
+ <div
10
+ class="envoc-form-date-picker envoc-form-group"
11
+ >
12
+ <div
13
+ id="favoritedate-error-scroll-target"
14
+ style="display: none;"
15
+ />
16
+ <label
17
+ for="favoriteDate"
18
+ >
19
+ Favorite Date
20
+ </label>
21
+ <div
22
+ class="react-date-picker react-date-picker--closed react-date-picker--enabled envoc-form-date-picker"
23
+ >
24
+ <div
25
+ class="react-date-picker__wrapper"
26
+ >
27
+ <div
28
+ class="react-date-picker__inputGroup"
29
+ >
30
+ <input
31
+ max="2023-09-23"
32
+ min="2022-06-22"
33
+ name="date"
34
+ style="visibility: hidden; position: absolute; z-index: -999;"
35
+ type="date"
36
+ value=""
37
+ />
38
+ <input
39
+ autocomplete="off"
40
+ class="react-date-picker__inputGroup__input react-date-picker__inputGroup__month"
41
+ data-input="true"
42
+ inputmode="numeric"
43
+ max="12"
44
+ min="1"
45
+ name="month"
46
+ placeholder="mm"
47
+ type="number"
48
+ value=""
49
+ />
50
+ <span
51
+ class="react-date-picker__inputGroup__divider"
52
+ >
53
+ /
54
+ </span>
55
+ <input
56
+ autocomplete="off"
57
+ class="react-date-picker__inputGroup__input react-date-picker__inputGroup__day"
58
+ data-input="true"
59
+ inputmode="numeric"
60
+ max="31"
61
+ min="1"
62
+ name="day"
63
+ placeholder="dd"
64
+ type="number"
65
+ value=""
66
+ />
67
+ <span
68
+ class="react-date-picker__inputGroup__divider"
69
+ >
70
+ /
71
+ </span>
72
+ <input
73
+ autocomplete="off"
74
+ class="react-date-picker__inputGroup__input react-date-picker__inputGroup__year"
75
+ data-input="true"
76
+ inputmode="numeric"
77
+ max="2023"
78
+ min="2022"
79
+ name="year"
80
+ placeholder="yyyy"
81
+ step="1"
82
+ type="number"
83
+ value=""
84
+ />
85
+ </div>
86
+ <button
87
+ class="react-date-picker__clear-button react-date-picker__button"
88
+ type="button"
89
+ >
90
+ <svg
91
+ class="react-date-picker__clear-button__icon react-date-picker__button__icon"
92
+ height="19"
93
+ stroke="black"
94
+ stroke-width="2"
95
+ viewBox="0 0 19 19"
96
+ width="19"
97
+ xmlns="http://www.w3.org/2000/svg"
98
+ >
99
+ <line
100
+ x1="4"
101
+ x2="15"
102
+ y1="4"
103
+ y2="15"
104
+ />
105
+ <line
106
+ x1="15"
107
+ x2="4"
108
+ y1="4"
109
+ y2="15"
110
+ />
111
+ </svg>
112
+ </button>
113
+ <button
114
+ class="react-date-picker__calendar-button react-date-picker__button"
115
+ type="button"
116
+ >
117
+ <svg
118
+ class="react-date-picker__calendar-button__icon react-date-picker__button__icon"
119
+ height="19"
120
+ stroke="black"
121
+ stroke-width="2"
122
+ viewBox="0 0 19 19"
123
+ width="19"
124
+ xmlns="http://www.w3.org/2000/svg"
125
+ >
126
+ <rect
127
+ fill="none"
128
+ height="15"
129
+ width="15"
130
+ x="2"
131
+ y="2"
132
+ />
133
+ <line
134
+ x1="6"
135
+ x2="6"
136
+ y1="0"
137
+ y2="4"
138
+ />
139
+ <line
140
+ x1="13"
141
+ x2="13"
142
+ y1="0"
143
+ y2="4"
144
+ />
145
+ </svg>
146
+ </button>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ </form>
151
+ </DocumentFragment>
152
+ `;
@@ -1,10 +1,10 @@
1
- export interface CustomFieldInputProps<TValue> {
2
- id: string;
3
- name: string;
4
- value: TValue;
5
- // we want to be more strict than formik is for setting the value
6
- onChange: (newValue: TValue) => void;
7
-
8
- // we don't want controlled vs uncontrolled components to behave oddly
9
- onBlur: () => void;
10
- }
1
+ export interface CustomFieldInputProps<TValue> {
2
+ id: string;
3
+ name: string;
4
+ value: TValue;
5
+ // we want to be more strict than formik is for setting the value
6
+ onChange: (newValue: TValue) => void;
7
+
8
+ // we don't want controlled vs uncontrolled components to behave oddly
9
+ onBlur: () => void;
10
+ }
@@ -1,5 +1,5 @@
1
- import { FieldMetaProps } from 'formik';
2
-
3
- export interface CustomFieldMetaProps<TValue> extends FieldMetaProps<TValue> {
4
- warning: string | undefined;
5
- }
1
+ import { FieldMetaProps } from 'formik';
2
+
3
+ export interface CustomFieldMetaProps<TValue> extends FieldMetaProps<TValue> {
4
+ warning: string | undefined;
5
+ }
@@ -1,113 +1,113 @@
1
- import React, { ComponentProps, ElementType, LegacyRef } from 'react';
2
- import { FieldNameContext } from './FieldNameContext';
3
- import { InjectedFieldProps } from './InjectedFieldProps';
4
- import useStandardFormInput from './useStandardField';
5
- import { NormalizationFunction } from '../Normalization/NormalizationFunction';
6
- import { ValidationFunction } from '../Validation/ValidationFunction';
7
- import { required as requiredValidator } from '../Validation/validators';
8
-
9
- // we attempted to support generic components but failed
10
- // so, we assume the actual TRenderComponent has no generic arguments
11
- // instead, any concrete TRenderComponent can utilize a TRenderComponent<TValue> as needed
12
-
13
- export type RenderComponent<
14
- TValue,
15
- TRenderComponent extends ElementType
16
- > = Partial<ComponentProps<TRenderComponent>> extends Partial<
17
- InjectedFieldProps<TValue | undefined | null>
18
- >
19
- ? TRenderComponent
20
- : never;
21
-
22
- export type RenderComponentProps<
23
- TValue,
24
- TRenderComponent extends ElementType
25
- > = Partial<ComponentProps<TRenderComponent>> extends Partial<
26
- InjectedFieldProps<TValue | undefined | null>
27
- >
28
- ? ComponentProps<TRenderComponent>
29
- : never;
30
-
31
- /** A specific Field instance to be rendered by the given TRenderComponent or by whatever default is reasonable */
32
- export type FieldProps<
33
- TForm extends object,
34
- TProp extends keyof TForm,
35
- TRenderComponent extends ElementType
36
- > = {
37
- /** Name of the field. Used on submission. */
38
- name: TProp; // somewhat duplicated from useStandardFormInputProps but better for autocomplete
39
- /** Component to be rendered. Usually this is a type of input group e.g. `<StringInputGroup/>` */
40
- Component: RenderComponent<TForm[TProp], TRenderComponent>;
41
- /** Id of the field. */
42
- id?: string;
43
- /** Whether the field should be disabled. */
44
- disabled?: boolean;
45
- /** Client side validation functions */
46
- validate?:
47
- | ValidationFunction<TForm[TProp]>
48
- | ValidationFunction<TForm[TProp]>[];
49
- /** Function to modify the field value without making the form dirty. (e.g. phone number) */
50
- normalize?: NormalizationFunction<TForm[TProp]>;
51
- } & Omit<
52
- RenderComponentProps<TForm[TProp], TRenderComponent>,
53
- keyof InjectedFieldProps<TForm[TProp]>
54
- >;
55
-
56
- /**
57
- * Renders whatever Component is passed - injecting the formik values needed to finish wiring up that individual field.
58
- * Should no Component be used then the default will be provided by the default lookup based on typeof(TForm[TProp])
59
- */
60
- function Field<
61
- TForm extends object,
62
- TProp extends keyof TForm,
63
- TRenderComponent extends ElementType
64
- >(
65
- {
66
- name,
67
- Component,
68
- id,
69
- disabled,
70
- validate,
71
- normalize,
72
- ...rest
73
- }: FieldProps<TForm, TProp, TRenderComponent>,
74
- ref: LegacyRef<any>
75
- ) {
76
- const [input, meta] = useStandardFormInput<TForm[TProp]>({
77
- name: String(name),
78
- id: id,
79
- disabled: disabled,
80
- validate: validate,
81
- normalize: normalize,
82
- });
83
-
84
- const isRequired =
85
- rest?.required !== undefined
86
- ? rest.required
87
- : validate === requiredValidator ||
88
- (Array.isArray(validate) && validate.includes(requiredValidator));
89
-
90
- // a bit of a hack so JSX is happy with us
91
- const Wrapped = Component as React.ComponentType<
92
- InjectedFieldProps<TForm[TProp]>
93
- >;
94
-
95
- return (
96
- <FieldNameContext.Provider value={input.name}>
97
- <Wrapped
98
- {...rest}
99
- ref={ref}
100
- id={input.id}
101
- input={input}
102
- meta={meta}
103
- required={isRequired}
104
- disabled={disabled}
105
- />
106
- </FieldNameContext.Provider>
107
- );
108
- }
109
-
110
- // hack to get forwarded refs to work
111
- const FieldWithRef = React.forwardRef(Field as any);
112
-
113
- export default FieldWithRef as typeof Field;
1
+ import React, { ComponentProps, ElementType, LegacyRef } from 'react';
2
+ import { FieldNameContext } from './FieldNameContext';
3
+ import { InjectedFieldProps } from './InjectedFieldProps';
4
+ import useStandardFormInput from './useStandardField';
5
+ import { NormalizationFunction } from '../Normalization/NormalizationFunction';
6
+ import { ValidationFunction } from '../Validation/ValidationFunction';
7
+ import { required as requiredValidator } from '../Validation/validators';
8
+
9
+ // we attempted to support generic components but failed
10
+ // so, we assume the actual TRenderComponent has no generic arguments
11
+ // instead, any concrete TRenderComponent can utilize a TRenderComponent<TValue> as needed
12
+
13
+ export type RenderComponent<
14
+ TValue,
15
+ TRenderComponent extends ElementType
16
+ > = Partial<ComponentProps<TRenderComponent>> extends Partial<
17
+ InjectedFieldProps<TValue | undefined | null>
18
+ >
19
+ ? TRenderComponent
20
+ : never;
21
+
22
+ export type RenderComponentProps<
23
+ TValue,
24
+ TRenderComponent extends ElementType
25
+ > = Partial<ComponentProps<TRenderComponent>> extends Partial<
26
+ InjectedFieldProps<TValue | undefined | null>
27
+ >
28
+ ? ComponentProps<TRenderComponent>
29
+ : never;
30
+
31
+ /** A specific Field instance to be rendered by the given TRenderComponent or by whatever default is reasonable */
32
+ export type FieldProps<
33
+ TForm extends object,
34
+ TProp extends keyof TForm,
35
+ TRenderComponent extends ElementType
36
+ > = {
37
+ /** Name of the field. Used on submission. */
38
+ name: TProp; // somewhat duplicated from useStandardFormInputProps but better for autocomplete
39
+ /** Component to be rendered. Usually this is a type of input group e.g. `<StringInputGroup/>` */
40
+ Component: RenderComponent<TForm[TProp], TRenderComponent>;
41
+ /** Id of the field. */
42
+ id?: string;
43
+ /** Whether the field should be disabled. */
44
+ disabled?: boolean;
45
+ /** Client side validation functions */
46
+ validate?:
47
+ | ValidationFunction<TForm[TProp]>
48
+ | ValidationFunction<TForm[TProp]>[];
49
+ /** Function to modify the field value without making the form dirty. (e.g. phone number) */
50
+ normalize?: NormalizationFunction<TForm[TProp]>;
51
+ } & Omit<
52
+ RenderComponentProps<TForm[TProp], TRenderComponent>,
53
+ keyof InjectedFieldProps<TForm[TProp]>
54
+ >;
55
+
56
+ /**
57
+ * Renders whatever Component is passed - injecting the formik values needed to finish wiring up that individual field.
58
+ * Should no Component be used then the default will be provided by the default lookup based on typeof(TForm[TProp])
59
+ */
60
+ function Field<
61
+ TForm extends object,
62
+ TProp extends keyof TForm,
63
+ TRenderComponent extends ElementType
64
+ >(
65
+ {
66
+ name,
67
+ Component,
68
+ id,
69
+ disabled,
70
+ validate,
71
+ normalize,
72
+ ...rest
73
+ }: FieldProps<TForm, TProp, TRenderComponent>,
74
+ ref: LegacyRef<any>
75
+ ) {
76
+ const [input, meta] = useStandardFormInput<TForm[TProp]>({
77
+ name: String(name),
78
+ id: id,
79
+ disabled: disabled,
80
+ validate: validate,
81
+ normalize: normalize,
82
+ });
83
+
84
+ const isRequired =
85
+ rest?.required !== undefined
86
+ ? rest.required
87
+ : validate === requiredValidator ||
88
+ (Array.isArray(validate) && validate.includes(requiredValidator));
89
+
90
+ // a bit of a hack so JSX is happy with us
91
+ const Wrapped = Component as React.ComponentType<
92
+ InjectedFieldProps<TForm[TProp]>
93
+ >;
94
+
95
+ return (
96
+ <FieldNameContext.Provider value={input.name}>
97
+ <Wrapped
98
+ {...rest}
99
+ ref={ref}
100
+ id={input.id}
101
+ input={input}
102
+ meta={meta}
103
+ required={isRequired}
104
+ disabled={disabled}
105
+ />
106
+ </FieldNameContext.Provider>
107
+ );
108
+ }
109
+
110
+ // hack to get forwarded refs to work
111
+ const FieldWithRef = React.forwardRef(Field as any);
112
+
113
+ export default FieldWithRef as typeof Field;
@@ -1,12 +1,12 @@
1
- import { useContext } from 'react';
2
- import { FieldNameContext } from './FieldNameContext';
3
-
4
- /** Hidden `<div/>` that acts as an anchor to scroll to when a form error occurs. */
5
- export default function FieldErrorScrollTarget() {
6
- const name = useContext(FieldNameContext);
7
- if (!name) {
8
- return null;
9
- }
10
- const divId = `${name.toLowerCase()}-error-scroll-target`;
11
- return <div id={divId} style={{ display: 'none' }} />;
12
- }
1
+ import { useContext } from 'react';
2
+ import { FieldNameContext } from './FieldNameContext';
3
+
4
+ /** Hidden `<div/>` that acts as an anchor to scroll to when a form error occurs. */
5
+ export default function FieldErrorScrollTarget() {
6
+ const name = useContext(FieldNameContext);
7
+ if (!name) {
8
+ return null;
9
+ }
10
+ const divId = `${name.toLowerCase()}-error-scroll-target`;
11
+ return <div id={divId} style={{ display: 'none' }} />;
12
+ }
@@ -1,6 +1,6 @@
1
- import React from 'react';
2
-
3
- /** provides the full, qualified name of the current field name - including nested fields, path/dot delimited */
4
- export const FieldNameContext = React.createContext<string | undefined>(
5
- undefined
6
- );
1
+ import React from 'react';
2
+
3
+ /** provides the full, qualified name of the current field name - including nested fields, path/dot delimited */
4
+ export const FieldNameContext = React.createContext<string | undefined>(
5
+ undefined
6
+ );
@@ -1,18 +1,18 @@
1
- import React, { useContext } from 'react';
2
- import { FieldNameContext } from './FieldNameContext';
3
-
4
- interface FieldSectionProps {
5
- children: React.ReactNode;
6
- name: string;
7
- }
8
-
9
- export default function FieldSection({ children, name }: FieldSectionProps) {
10
- const parentContext = useContext(FieldNameContext);
11
- const effectiveValue = parentContext ? `${parentContext}.${name}` : name;
12
-
13
- return (
14
- <FieldNameContext.Provider value={effectiveValue}>
15
- {children}
16
- </FieldNameContext.Provider>
17
- );
18
- }
1
+ import React, { useContext } from 'react';
2
+ import { FieldNameContext } from './FieldNameContext';
3
+
4
+ interface FieldSectionProps {
5
+ children: React.ReactNode;
6
+ name: string;
7
+ }
8
+
9
+ export default function FieldSection({ children, name }: FieldSectionProps) {
10
+ const parentContext = useContext(FieldNameContext);
11
+ const effectiveValue = parentContext ? `${parentContext}.${name}` : name;
12
+
13
+ return (
14
+ <FieldNameContext.Provider value={effectiveValue}>
15
+ {children}
16
+ </FieldNameContext.Provider>
17
+ );
18
+ }
@@ -1,8 +1,8 @@
1
- import { CustomFieldInputProps } from './CustomFieldInputProps';
2
- import { CustomFieldMetaProps } from './CustomFieldMetaProps';
3
-
4
- /** Defines what is injected by a Field wrapper of some TRenderComponent */
5
- export interface InjectedFieldProps<TValue> {
6
- input: CustomFieldInputProps<TValue>;
7
- meta: CustomFieldMetaProps<TValue>;
8
- }
1
+ import { CustomFieldInputProps } from './CustomFieldInputProps';
2
+ import { CustomFieldMetaProps } from './CustomFieldMetaProps';
3
+
4
+ /** Defines what is injected by a Field wrapper of some TRenderComponent */
5
+ export interface InjectedFieldProps<TValue> {
6
+ input: CustomFieldInputProps<TValue>;
7
+ meta: CustomFieldMetaProps<TValue>;
8
+ }