envoc-form 5.0.3 → 5.0.4-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/README.md +4650 -1250
  2. package/dist/index.cjs +21523 -0
  3. package/dist/index.d.ts +575 -0
  4. package/dist/index.js +21456 -0
  5. package/package.json +107 -111
  6. package/dist/css/envoc-form-styles.css +0 -3
  7. package/dist/css/envoc-form-styles.css.map +0 -1
  8. package/es/AddressInput/AddressInput.d.ts +0 -24
  9. package/es/AddressInput/AddressInput.js +0 -20
  10. package/es/AddressInput/UsStates.d.ts +0 -3
  11. package/es/AddressInput/UsStates.js +0 -53
  12. package/es/ConfirmBaseForm/ConfirmBaseForm.d.ts +0 -26
  13. package/es/ConfirmBaseForm/ConfirmBaseForm.js +0 -42
  14. package/es/ConfirmDeleteForm/ConfirmDeleteForm.d.ts +0 -24
  15. package/es/ConfirmDeleteForm/ConfirmDeleteForm.js +0 -60
  16. package/es/DatePicker/DatePickerGroup.d.ts +0 -13
  17. package/es/DatePicker/DatePickerGroup.js +0 -87
  18. package/es/DatePicker/DatePickerHelper.d.ts +0 -3
  19. package/es/DatePicker/DatePickerHelper.js +0 -1
  20. package/es/DatePicker/StringDateOnlyPickerGroup.d.ts +0 -9
  21. package/es/DatePicker/StringDateOnlyPickerGroup.js +0 -29
  22. package/es/DatePicker/StringDatePickerGroup.d.ts +0 -9
  23. package/es/DatePicker/StringDatePickerGroup.js +0 -24
  24. package/es/Field/CustomFieldInputProps.d.ts +0 -7
  25. package/es/Field/CustomFieldInputProps.js +0 -1
  26. package/es/Field/CustomFieldMetaProps.d.ts +0 -4
  27. package/es/Field/CustomFieldMetaProps.js +0 -1
  28. package/es/Field/Field.d.ts +0 -28
  29. package/es/Field/Field.js +0 -51
  30. package/es/Field/FieldErrorScrollTarget.d.ts +0 -2
  31. package/es/Field/FieldErrorScrollTarget.js +0 -12
  32. package/es/Field/FieldNameContext.d.ts +0 -3
  33. package/es/Field/FieldNameContext.js +0 -3
  34. package/es/Field/FieldSection.d.ts +0 -7
  35. package/es/Field/FieldSection.js +0 -9
  36. package/es/Field/InjectedFieldProps.d.ts +0 -7
  37. package/es/Field/InjectedFieldProps.js +0 -1
  38. package/es/Field/StandAloneInput.d.ts +0 -13
  39. package/es/Field/StandAloneInput.js +0 -50
  40. package/es/Field/useStandardField.d.ts +0 -21
  41. package/es/Field/useStandardField.js +0 -92
  42. package/es/FieldArray/FieldArray.d.ts +0 -24
  43. package/es/FieldArray/FieldArray.js +0 -77
  44. package/es/File/FileGroup.d.ts +0 -10
  45. package/es/File/FileGroup.js +0 -53
  46. package/es/File/FileList.d.ts +0 -5
  47. package/es/File/FileList.js +0 -10
  48. package/es/File/humanFileSize.d.ts +0 -1
  49. package/es/File/humanFileSize.js +0 -6
  50. package/es/Form/FocusError.d.ts +0 -7
  51. package/es/Form/FocusError.js +0 -42
  52. package/es/Form/Form.d.ts +0 -33
  53. package/es/Form/Form.js +0 -141
  54. package/es/Form/FormBasedPreventNavigation.d.ts +0 -6
  55. package/es/Form/FormBasedPreventNavigation.js +0 -20
  56. package/es/Form/LegacyFormBasedPreventNavigation.d.ts +0 -17
  57. package/es/Form/LegacyFormBasedPreventNavigation.js +0 -69
  58. package/es/Form/NewFormBasedPreventNavigation.d.ts +0 -14
  59. package/es/Form/NewFormBasedPreventNavigation.js +0 -39
  60. package/es/Form/ServerErrorContext.d.ts +0 -11
  61. package/es/Form/ServerErrorContext.js +0 -9
  62. package/es/FormActions.d.ts +0 -12
  63. package/es/FormActions.js +0 -16
  64. package/es/FormDefaults.d.ts +0 -4
  65. package/es/FormDefaults.js +0 -2
  66. package/es/Group.d.ts +0 -16
  67. package/es/Group.js +0 -14
  68. package/es/Input/IconInputGroup.d.ts +0 -12
  69. package/es/Input/IconInputGroup.js +0 -43
  70. package/es/Input/InputGroup.d.ts +0 -12
  71. package/es/Input/InputGroup.js +0 -34
  72. package/es/Input/MoneyInputGroup.d.ts +0 -9
  73. package/es/Input/MoneyInputGroup.js +0 -43
  74. package/es/Input/NumberInputGroup.d.ts +0 -9
  75. package/es/Input/NumberInputGroup.js +0 -43
  76. package/es/Input/PhoneNumberInputGroup.d.ts +0 -10
  77. package/es/Input/PhoneNumberInputGroup.js +0 -47
  78. package/es/Input/StringInputGroup.d.ts +0 -8
  79. package/es/Input/StringInputGroup.js +0 -43
  80. package/es/Normalization/NormalizationFunction.d.ts +0 -4
  81. package/es/Normalization/NormalizationFunction.js +0 -1
  82. package/es/Normalization/normalizers.d.ts +0 -4
  83. package/es/Normalization/normalizers.js +0 -32
  84. package/es/Select/BooleanSelectGroup.d.ts +0 -7
  85. package/es/Select/BooleanSelectGroup.js +0 -28
  86. package/es/Select/NumberSelectGroup.d.ts +0 -9
  87. package/es/Select/NumberSelectGroup.js +0 -21
  88. package/es/Select/SelectGroup.d.ts +0 -27
  89. package/es/Select/SelectGroup.js +0 -65
  90. package/es/Select/SelectGroupPropsHelper.d.ts +0 -3
  91. package/es/Select/SelectGroupPropsHelper.js +0 -1
  92. package/es/Select/StringSelectGroup.d.ts +0 -9
  93. package/es/Select/StringSelectGroup.js +0 -21
  94. package/es/StandardFormActions.d.ts +0 -11
  95. package/es/StandardFormActions.js +0 -14
  96. package/es/SubmitFormButton.d.ts +0 -10
  97. package/es/SubmitFormButton.js +0 -40
  98. package/es/TextArea/TextAreaGroup.d.ts +0 -9
  99. package/es/TextArea/TextAreaGroup.js +0 -35
  100. package/es/Validation/ValidatedApiResult.d.ts +0 -6
  101. package/es/Validation/ValidatedApiResult.js +0 -1
  102. package/es/Validation/ValidationError.d.ts +0 -5
  103. package/es/Validation/ValidationError.js +0 -1
  104. package/es/Validation/ValidationFunction.d.ts +0 -4
  105. package/es/Validation/ValidationFunction.js +0 -1
  106. package/es/Validation/validators.d.ts +0 -18
  107. package/es/Validation/validators.js +0 -77
  108. package/es/index.d.ts +0 -75
  109. package/es/index.js +0 -51
  110. package/es/setupTests.d.ts +0 -1
  111. package/es/setupTests.js +0 -1
  112. package/es/utils/objectContainsNonSerializableProperty.d.ts +0 -1
  113. package/es/utils/objectContainsNonSerializableProperty.js +0 -14
  114. package/es/utils/objectToFormData.d.ts +0 -10
  115. package/es/utils/objectToFormData.js +0 -77
  116. package/es/utils/typeChecks.d.ts +0 -8
  117. package/es/utils/typeChecks.js +0 -18
  118. package/lib/AddressInput/AddressInput.d.ts +0 -24
  119. package/lib/AddressInput/AddressInput.js +0 -26
  120. package/lib/AddressInput/UsStates.d.ts +0 -3
  121. package/lib/AddressInput/UsStates.js +0 -55
  122. package/lib/ConfirmBaseForm/ConfirmBaseForm.d.ts +0 -26
  123. package/lib/ConfirmBaseForm/ConfirmBaseForm.js +0 -48
  124. package/lib/ConfirmDeleteForm/ConfirmDeleteForm.d.ts +0 -24
  125. package/lib/ConfirmDeleteForm/ConfirmDeleteForm.js +0 -66
  126. package/lib/DatePicker/DatePickerGroup.d.ts +0 -13
  127. package/lib/DatePicker/DatePickerGroup.js +0 -95
  128. package/lib/DatePicker/DatePickerHelper.d.ts +0 -3
  129. package/lib/DatePicker/DatePickerHelper.js +0 -2
  130. package/lib/DatePicker/StringDateOnlyPickerGroup.d.ts +0 -9
  131. package/lib/DatePicker/StringDateOnlyPickerGroup.js +0 -35
  132. package/lib/DatePicker/StringDatePickerGroup.d.ts +0 -9
  133. package/lib/DatePicker/StringDatePickerGroup.js +0 -30
  134. package/lib/Field/CustomFieldInputProps.d.ts +0 -7
  135. package/lib/Field/CustomFieldInputProps.js +0 -2
  136. package/lib/Field/CustomFieldMetaProps.d.ts +0 -4
  137. package/lib/Field/CustomFieldMetaProps.js +0 -2
  138. package/lib/Field/Field.d.ts +0 -28
  139. package/lib/Field/Field.js +0 -56
  140. package/lib/Field/FieldErrorScrollTarget.d.ts +0 -2
  141. package/lib/Field/FieldErrorScrollTarget.js +0 -15
  142. package/lib/Field/FieldNameContext.d.ts +0 -3
  143. package/lib/Field/FieldNameContext.js +0 -9
  144. package/lib/Field/FieldSection.d.ts +0 -7
  145. package/lib/Field/FieldSection.js +0 -12
  146. package/lib/Field/InjectedFieldProps.d.ts +0 -7
  147. package/lib/Field/InjectedFieldProps.js +0 -2
  148. package/lib/Field/StandAloneInput.d.ts +0 -13
  149. package/lib/Field/StandAloneInput.js +0 -76
  150. package/lib/Field/useStandardField.d.ts +0 -21
  151. package/lib/Field/useStandardField.js +0 -95
  152. package/lib/FieldArray/FieldArray.d.ts +0 -24
  153. package/lib/FieldArray/FieldArray.js +0 -83
  154. package/lib/File/FileGroup.d.ts +0 -10
  155. package/lib/File/FileGroup.js +0 -58
  156. package/lib/File/FileList.d.ts +0 -5
  157. package/lib/File/FileList.js +0 -13
  158. package/lib/File/humanFileSize.d.ts +0 -1
  159. package/lib/File/humanFileSize.js +0 -10
  160. package/lib/Form/FocusError.d.ts +0 -7
  161. package/lib/Form/FocusError.js +0 -48
  162. package/lib/Form/Form.d.ts +0 -33
  163. package/lib/Form/Form.js +0 -147
  164. package/lib/Form/FormBasedPreventNavigation.d.ts +0 -6
  165. package/lib/Form/FormBasedPreventNavigation.js +0 -26
  166. package/lib/Form/LegacyFormBasedPreventNavigation.d.ts +0 -17
  167. package/lib/Form/LegacyFormBasedPreventNavigation.js +0 -72
  168. package/lib/Form/NewFormBasedPreventNavigation.d.ts +0 -14
  169. package/lib/Form/NewFormBasedPreventNavigation.js +0 -42
  170. package/lib/Form/ServerErrorContext.d.ts +0 -11
  171. package/lib/Form/ServerErrorContext.js +0 -15
  172. package/lib/FormActions.d.ts +0 -12
  173. package/lib/FormActions.js +0 -22
  174. package/lib/FormDefaults.d.ts +0 -4
  175. package/lib/FormDefaults.js +0 -5
  176. package/lib/Group.d.ts +0 -16
  177. package/lib/Group.js +0 -20
  178. package/lib/Input/IconInputGroup.d.ts +0 -12
  179. package/lib/Input/IconInputGroup.js +0 -48
  180. package/lib/Input/InputGroup.d.ts +0 -12
  181. package/lib/Input/InputGroup.js +0 -39
  182. package/lib/Input/MoneyInputGroup.d.ts +0 -9
  183. package/lib/Input/MoneyInputGroup.js +0 -48
  184. package/lib/Input/NumberInputGroup.d.ts +0 -9
  185. package/lib/Input/NumberInputGroup.js +0 -48
  186. package/lib/Input/PhoneNumberInputGroup.d.ts +0 -10
  187. package/lib/Input/PhoneNumberInputGroup.js +0 -52
  188. package/lib/Input/StringInputGroup.d.ts +0 -8
  189. package/lib/Input/StringInputGroup.js +0 -48
  190. package/lib/Normalization/NormalizationFunction.d.ts +0 -4
  191. package/lib/Normalization/NormalizationFunction.js +0 -2
  192. package/lib/Normalization/normalizers.d.ts +0 -4
  193. package/lib/Normalization/normalizers.js +0 -37
  194. package/lib/Select/BooleanSelectGroup.d.ts +0 -7
  195. package/lib/Select/BooleanSelectGroup.js +0 -35
  196. package/lib/Select/NumberSelectGroup.d.ts +0 -9
  197. package/lib/Select/NumberSelectGroup.js +0 -29
  198. package/lib/Select/SelectGroup.d.ts +0 -27
  199. package/lib/Select/SelectGroup.js +0 -71
  200. package/lib/Select/SelectGroupPropsHelper.d.ts +0 -3
  201. package/lib/Select/SelectGroupPropsHelper.js +0 -2
  202. package/lib/Select/StringSelectGroup.d.ts +0 -9
  203. package/lib/Select/StringSelectGroup.js +0 -29
  204. package/lib/StandardFormActions.d.ts +0 -11
  205. package/lib/StandardFormActions.js +0 -20
  206. package/lib/SubmitFormButton.d.ts +0 -10
  207. package/lib/SubmitFormButton.js +0 -45
  208. package/lib/TextArea/TextAreaGroup.d.ts +0 -9
  209. package/lib/TextArea/TextAreaGroup.js +0 -40
  210. package/lib/Validation/ValidatedApiResult.d.ts +0 -6
  211. package/lib/Validation/ValidatedApiResult.js +0 -2
  212. package/lib/Validation/ValidationError.d.ts +0 -5
  213. package/lib/Validation/ValidationError.js +0 -2
  214. package/lib/Validation/ValidationFunction.d.ts +0 -4
  215. package/lib/Validation/ValidationFunction.js +0 -2
  216. package/lib/Validation/validators.d.ts +0 -18
  217. package/lib/Validation/validators.js +0 -90
  218. package/lib/index.d.ts +0 -75
  219. package/lib/index.js +0 -119
  220. package/lib/setupTests.d.ts +0 -1
  221. package/lib/setupTests.js +0 -3
  222. package/lib/utils/objectContainsNonSerializableProperty.d.ts +0 -1
  223. package/lib/utils/objectContainsNonSerializableProperty.js +0 -17
  224. package/lib/utils/objectToFormData.d.ts +0 -10
  225. package/lib/utils/objectToFormData.js +0 -79
  226. package/lib/utils/typeChecks.d.ts +0 -8
  227. package/lib/utils/typeChecks.js +0 -29
  228. package/src/AddressInput/AddressInput.test.tsx +0 -27
  229. package/src/AddressInput/AddressInput.tsx +0 -82
  230. package/src/AddressInput/UsStates.ts +0 -55
  231. package/src/AddressInput/__snapshots__/AddressInput.test.tsx.snap +0 -182
  232. package/src/ConfirmBaseForm/ConfirmBaseForm.test.tsx +0 -24
  233. package/src/ConfirmBaseForm/ConfirmBaseForm.tsx +0 -74
  234. package/src/ConfirmBaseForm/__snapshots__/ConfirmBaseForm.test.tsx.snap +0 -23
  235. package/src/ConfirmDeleteForm/ConfirmDeleteForm.test.tsx +0 -24
  236. package/src/ConfirmDeleteForm/ConfirmDeleteForm.tsx +0 -87
  237. package/src/ConfirmDeleteForm/__snapshots__/ConfirmDeleteForm.test.tsx.snap +0 -25
  238. package/src/DatePicker/DatePicker.test.tsx +0 -48
  239. package/src/DatePicker/DatePickerGroup.tsx +0 -115
  240. package/src/DatePicker/DatePickerHelper.ts +0 -4
  241. package/src/DatePicker/StringDateOnlyPickerGroup.tsx +0 -28
  242. package/src/DatePicker/StringDatePickerGroup.tsx +0 -20
  243. package/src/DatePicker/__snapshots__/DatePicker.test.tsx.snap +0 -152
  244. package/src/Field/CustomFieldInputProps.ts +0 -10
  245. package/src/Field/CustomFieldMetaProps.ts +0 -5
  246. package/src/Field/Field.tsx +0 -113
  247. package/src/Field/FieldErrorScrollTarget.tsx +0 -12
  248. package/src/Field/FieldNameContext.ts +0 -6
  249. package/src/Field/FieldSection.tsx +0 -18
  250. package/src/Field/InjectedFieldProps.ts +0 -8
  251. package/src/Field/StandAloneInput.tsx +0 -55
  252. package/src/Field/useStandardField.ts +0 -125
  253. package/src/FieldArray/FieldArray.tsx +0 -154
  254. package/src/File/FileGroup.test.tsx +0 -35
  255. package/src/File/FileGroup.tsx +0 -85
  256. package/src/File/FileList.tsx +0 -21
  257. package/src/File/__snapshots__/FileGroup.test.tsx.snap +0 -34
  258. package/src/File/humanFileSize.ts +0 -8
  259. package/src/Form/FocusError.tsx +0 -55
  260. package/src/Form/Form.test.tsx +0 -14
  261. package/src/Form/Form.tsx +0 -237
  262. package/src/Form/FormBasedPreventNavigation.tsx +0 -56
  263. package/src/Form/LegacyFormBasedPreventNavigation.tsx +0 -77
  264. package/src/Form/NewFormBasedPreventNavigation.tsx +0 -59
  265. package/src/Form/ServerErrorContext.ts +0 -18
  266. package/src/Form/__snapshots__/Form.test.tsx.snap +0 -10
  267. package/src/FormActions.tsx +0 -47
  268. package/src/FormDefaults.ts +0 -2
  269. package/src/Group.tsx +0 -62
  270. package/src/Input/IconInputGroup.tsx +0 -54
  271. package/src/Input/InputGroup.tsx +0 -72
  272. package/src/Input/MoneyInputGroup.tsx +0 -50
  273. package/src/Input/NumberInputGroup.tsx +0 -48
  274. package/src/Input/PhoneNumberInputGroup.tsx +0 -45
  275. package/src/Input/StringInputGroup.tsx +0 -53
  276. package/src/Input/__Tests__/IconInputGroup.test.tsx +0 -35
  277. package/src/Input/__Tests__/MoneyInputGroup.test.tsx +0 -37
  278. package/src/Input/__Tests__/NumberInputGroup.test.tsx +0 -35
  279. package/src/Input/__Tests__/PhoneNumberInputGroup.test.tsx +0 -36
  280. package/src/Input/__Tests__/StringInputGroup.test.tsx +0 -27
  281. package/src/Input/__Tests__/__snapshots__/IconInputGroup.test.tsx.snap +0 -32
  282. package/src/Input/__Tests__/__snapshots__/MoneyInputGroup.test.tsx.snap +0 -34
  283. package/src/Input/__Tests__/__snapshots__/NumberInputGroup.test.tsx.snap +0 -32
  284. package/src/Input/__Tests__/__snapshots__/PhoneNumberInputGroup.test.tsx.snap +0 -33
  285. package/src/Input/__Tests__/__snapshots__/StringInputGroup.test.tsx.snap +0 -31
  286. package/src/Normalization/NormalizationFunction.ts +0 -4
  287. package/src/Normalization/normalizers.ts +0 -44
  288. package/src/Select/BooleanSelectGroup.tsx +0 -28
  289. package/src/Select/NumberSelectGroup.tsx +0 -16
  290. package/src/Select/SelectGroup.tsx +0 -124
  291. package/src/Select/SelectGroupPropsHelper.ts +0 -4
  292. package/src/Select/StringSelectGroup.tsx +0 -16
  293. package/src/Select/__tests__/BooleanSelectGroup.test.tsx +0 -35
  294. package/src/Select/__tests__/NumberSelectGroup.test.tsx +0 -87
  295. package/src/Select/__tests__/StringSelectGroup.test.tsx +0 -89
  296. package/src/Select/__tests__/__snapshots__/BooleanSelectGroup.test.tsx.snap +0 -98
  297. package/src/Select/__tests__/__snapshots__/NumberSelectGroup.test.tsx.snap +0 -195
  298. package/src/Select/__tests__/__snapshots__/StringSelectGroup.test.tsx.snap +0 -195
  299. package/src/StandardFormActions.tsx +0 -41
  300. package/src/SubmitFormButton.tsx +0 -54
  301. package/src/TextArea/TextAreaGroup.tsx +0 -64
  302. package/src/Validation/ValidatedApiResult.ts +0 -8
  303. package/src/Validation/ValidationError.ts +0 -6
  304. package/src/Validation/ValidationFunction.ts +0 -4
  305. package/src/Validation/validators.test.tsx +0 -81
  306. package/src/Validation/validators.ts +0 -97
  307. package/src/__Tests__/FormTestBase.tsx +0 -64
  308. package/src/__Tests__/RealisticForm.test.tsx +0 -82
  309. package/src/__Tests__/StandardFormActions.test.tsx +0 -17
  310. package/src/__Tests__/SubmitFormButton.test.tsx +0 -17
  311. package/src/__Tests__/__snapshots__/StandardFormActions.test.tsx.snap +0 -27
  312. package/src/__Tests__/__snapshots__/SubmitFormButton.test.tsx.snap +0 -20
  313. package/src/__Tests__/index.ts +0 -3
  314. package/src/_variables.scss +0 -11
  315. package/src/index.ts +0 -153
  316. package/src/react-app-env.d.ts +0 -1
  317. package/src/setupTests.ts +0 -1
  318. package/src/styles.scss +0 -0
  319. package/src/utils/objectContainsNonSerializableProperty.test.tsx +0 -49
  320. package/src/utils/objectContainsNonSerializableProperty.ts +0 -17
  321. package/src/utils/objectToFormData.test.tsx +0 -76
  322. package/src/utils/objectToFormData.ts +0 -105
  323. package/src/utils/typeChecks.ts +0 -18
@@ -1,55 +0,0 @@
1
- import { useEffect } from 'react';
2
- import { useFormikContext } from 'formik';
3
- import smoothscroll from 'smoothscroll-polyfill';
4
- import { ServerErrorContextProps } from './ServerErrorContext';
5
-
6
- export interface FocusErrorProps {
7
- /** Validation errors that have been received from the server. */
8
- serverErrors: ServerErrorContextProps;
9
- }
10
-
11
- /** Function to scroll to the field that has an error. */
12
- export default function FocusError(props: FocusErrorProps) {
13
- const { errors, isSubmitting, isValidating } = useFormikContext();
14
- smoothscroll.polyfill();
15
- useEffect(() => {
16
- if (!isSubmitting || isValidating) {
17
- return;
18
- }
19
- //This block handles any front-end input validation errors
20
- //e.g. required fields, max characters, etc
21
- const keys = Object.keys(errors);
22
- if (keys.length > 0) {
23
- return scrollToErrorElement(keys);
24
- }
25
- //This block handles any input-specific server-side errors
26
- //e.g. improper email formatting, invalid phone number, etc.
27
- if (
28
- props.serverErrors.errors &&
29
- Object.values(props.serverErrors.errors).some((x) => !!x)
30
- ) {
31
- const names = Object.keys(props.serverErrors.errors);
32
- return scrollToErrorElement(names);
33
- }
34
- }, [errors, isSubmitting, isValidating, props]);
35
- return null;
36
- }
37
-
38
- const scrollToErrorElement = (keys: string[]) => {
39
- let firstErrorElement: HTMLElement | null = document.getElementById(
40
- `${keys[0].toLowerCase()}-error-scroll-target`
41
- );
42
- if (!firstErrorElement || !firstErrorElement.parentNode) {
43
- return;
44
- }
45
- firstErrorElement = firstErrorElement.parentNode as HTMLElement;
46
- const headerOffset = -110;
47
- const y =
48
- firstErrorElement.getBoundingClientRect().top +
49
- window.pageYOffset +
50
- headerOffset;
51
- window.scrollTo({ top: y, behavior: 'smooth' });
52
- setTimeout(() => {
53
- firstErrorElement?.focus();
54
- }, 500);
55
- };
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
- import FormTestBase from '../__Tests__/FormTestBase';
4
-
5
- describe('FormTestBase', () => {
6
- it('renders without crashing', () => {
7
- render(<FormTestBase>{() => <></>}</FormTestBase>);
8
- });
9
-
10
- it('has matching snapshot', () => {
11
- const renderResult = render(<FormTestBase>{() => <></>}</FormTestBase>);
12
- expect(renderResult.asFragment()).toMatchSnapshot();
13
- });
14
- });
package/src/Form/Form.tsx DELETED
@@ -1,237 +0,0 @@
1
- import {
2
- CSSProperties,
3
- ElementType,
4
- useContext,
5
- useMemo,
6
- useState,
7
- } from 'react';
8
- import classNames from 'classnames';
9
- import {
10
- Form as FormikFormWrapper,
11
- Formik,
12
- FormikHelpers,
13
- useFormikContext,
14
- } from 'formik';
15
- import FocusError from './FocusError';
16
- import FormBasedPreventNavigation from './FormBasedPreventNavigation';
17
- import {
18
- ServerErrorContext,
19
- ServerErrorContextProps,
20
- ServerErrors,
21
- } from './ServerErrorContext';
22
- import Field, { FieldProps } from '../Field/Field';
23
- import FieldArray, { FieldArrayProps } from '../FieldArray/FieldArray';
24
- import { FormDefaults } from '../FormDefaults';
25
- import objectContainsNonSerializableProperty from '../utils/objectContainsNonSerializableProperty';
26
- import objectToFormData from '../utils/objectToFormData';
27
- import { ValidatedApiResult } from '../Validation/ValidatedApiResult';
28
- import { ValidationError } from '../Validation/ValidationError';
29
-
30
- // This exposes the builder that ensures only "name" values on the given TForm can be used
31
- // Further, each Field can then infer the proper type given the name
32
- export type FormBuilderProp<TForm extends object> = {
33
- // the first set of <> is a generic method signature - we don't split this off because we need the TForm closure
34
- Field: <TProp extends keyof TForm, TRenderComponent extends ElementType>(
35
- props: FieldProps<TForm, TProp, TRenderComponent>
36
- ) => JSX.Element; // assumes this is never null - thought he final component may not render
37
-
38
- FieldArray: <TProp extends keyof TForm>(
39
- props: FieldArrayProps<TForm, TProp>
40
- ) => JSX.Element;
41
- };
42
-
43
- export interface FullFormProps<TForm extends object> {
44
- /** The `<Field/>` and `<FieldArray/>` components. */
45
- children: (formBuilder: FormBuilderProp<TForm>) => JSX.Element;
46
- /** Submission handler */
47
- onSubmit: (
48
- formValues: TForm,
49
- formikBag: FormikHelpers<TForm>
50
- ) => Promise<ValidatedApiResult>;
51
- /** Submission handler for forms that use [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData).*/
52
- onFormDataSubmit: (
53
- formValues: FormData,
54
- formikBag: FormikHelpers<TForm>
55
- ) => Promise<ValidatedApiResult>;
56
- className?: string;
57
- style?: CSSProperties;
58
- /** Prevent the user from leaving the form if they have edited any field. This is presented as a JS `alert()`. */
59
- ignoreLostChanges?: boolean;
60
- /** The intitial values of the form. */
61
- initialValues?: TForm;
62
- }
63
-
64
- type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<
65
- T,
66
- Exclude<keyof T, Keys>
67
- > &
68
- {
69
- [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
70
- }[Keys];
71
-
72
- export type FormProps<TForm extends object> = RequireAtLeastOne<
73
- FullFormProps<TForm>,
74
- 'onSubmit' | 'onFormDataSubmit'
75
- >;
76
-
77
- /** Define a form. Uses [formik](https://formik.org/docs/overview). Usually contains many `<Field/>` components. */
78
- export default function Form<TForm extends object>({
79
- children,
80
- className,
81
- style,
82
- ignoreLostChanges,
83
- onSubmit,
84
- onFormDataSubmit,
85
- initialValues,
86
- ...props
87
- }: FormProps<TForm>) {
88
- // formik resets all error on each blur (with our settings)
89
- // this means that ALL errors from the server disappear when any one field is blurred
90
- // So, we have to store server errors ourselves
91
- // Since we only use useStandardFormInput, that means there is only one consumer
92
- const [serverErrors, setServerErrors] = useState<ServerErrors>({});
93
- const serverErrorContextValue = useMemo<ServerErrorContextProps>(
94
- () => ({
95
- errors: serverErrors,
96
- getError: (path) => {
97
- const lowered = path.toLowerCase();
98
- return serverErrors && serverErrors[lowered];
99
- },
100
- setError: (path, errorMessage) => {
101
- const lowered = path.toLowerCase();
102
- setServerErrors(
103
- Object.assign({}, serverErrors, {
104
- [lowered]: !errorMessage ? undefined : errorMessage,
105
- })
106
- );
107
- },
108
- }),
109
- [serverErrors]
110
- );
111
-
112
- return (
113
- <Formik
114
- validateOnChange={false}
115
- validateOnBlur={true}
116
- validateOnMount={false}
117
- initialValues={initialValues || ({} as TForm)}
118
- onSubmit={handleSubmit}
119
- {...props}>
120
- <ServerErrorContext.Provider value={serverErrorContextValue}>
121
- <FormikFormWrapper
122
- className={classNames(
123
- className,
124
- FormDefaults.cssClassPrefix + 'form'
125
- )}
126
- style={style}>
127
- <FocusError serverErrors={serverErrorContextValue} />
128
- <FormBasedPreventNavigation ignoreLostChanges={ignoreLostChanges} />
129
- {children({
130
- // hack for ref forwarding
131
- Field: Field as any,
132
- FieldArray: FieldArray as any,
133
- })}
134
- </FormikFormWrapper>
135
- </ServerErrorContext.Provider>
136
- </Formik>
137
- );
138
-
139
- function handleSubmit(values: TForm, formikBag: FormikHelpers<TForm>) {
140
- let formData: FormData | undefined = undefined;
141
- let submitFunc: () => Promise<ValidatedApiResult>;
142
- if (objectContainsNonSerializableProperty(values)) {
143
- formData = objectToFormData(values, {
144
- indices: true,
145
- dotNotation: true,
146
- allowEmptyArrays: true,
147
- noFileListBrackets: true,
148
- });
149
- if (onFormDataSubmit === undefined) {
150
- throw new Error(
151
- 'No onFormDataSubmit supplied for non-serializable properties.'
152
- );
153
- }
154
- submitFunc = () =>
155
- onFormDataSubmit(formData ?? new FormData(), formikBag);
156
- } else {
157
- if (onSubmit === undefined) {
158
- formData = objectToFormData(values, {
159
- indices: true,
160
- dotNotation: true,
161
- allowEmptyArrays: true,
162
- noFileListBrackets: true,
163
- });
164
- if (onFormDataSubmit === undefined) {
165
- // This error should never occur, as this case is covered by RequireAtLeastOne type safety
166
- throw new Error(
167
- 'No onFormDataSubmit supplied for non-serializable properties.'
168
- );
169
- }
170
- submitFunc = () =>
171
- onFormDataSubmit(formData ?? new FormData(), formikBag);
172
- } else {
173
- submitFunc = () => onSubmit(values, formikBag);
174
- }
175
- }
176
-
177
- return submitFunc()
178
- .then((response) => {
179
- return response;
180
- })
181
- .catch((err) => {
182
- //this is an http error
183
- if (
184
- err &&
185
- err.response &&
186
- err.response.data &&
187
- err.response.data.validationFailures
188
- ) {
189
- try {
190
- const serverErrors = err.response.data.validationFailures.reduce(
191
- (acc: ServerErrors, value: ValidationError) => {
192
- // for simplicity, just keep it to one server error at a time per path
193
- // don't care of the property name case changes
194
- const path = value.propertyName?.toLowerCase();
195
- if (!!path && !!value.errorMessage) {
196
- acc[path] = value.errorMessage;
197
- }
198
- return acc;
199
- },
200
- {} as ServerErrors
201
- );
202
- setServerErrors(serverErrors);
203
- } catch (err) {
204
- console.error('Failure to getErrorObject');
205
- console.error(err);
206
- throw err;
207
- }
208
- }
209
- throw err;
210
- });
211
- }
212
- }
213
-
214
- Form.DisplayFormState = DisplayFormState;
215
- function DisplayFormState() {
216
- const formState = useFormikContext();
217
- const serverErrorContext = useContext(ServerErrorContext);
218
- return (
219
- <div style={{ margin: '1rem 0' }}>
220
- <pre
221
- style={{
222
- background: '#f6f8fa',
223
- fontSize: '.65rem',
224
- padding: '.5rem',
225
- }}>
226
- {serverErrorContext && serverErrorContext.errors && (
227
- <div>
228
- <strong>serverErrors = </strong>
229
- {JSON.stringify(serverErrorContext.errors, null, 2)}
230
- </div>
231
- )}
232
- <strong>formState = </strong>
233
- {JSON.stringify(formState, null, 2)}
234
- </pre>
235
- </div>
236
- );
237
- }
@@ -1,56 +0,0 @@
1
- import type { History } from 'history';
2
- import { ContextType, useContext } from 'react';
3
- import {
4
- Navigator as BaseNavigator,
5
- UNSAFE_NavigationContext as NavigationContext,
6
- } from 'react-router-dom';
7
- import { useFormikContext } from 'formik';
8
- import LegacyFormBasedPreventNavigation from './LegacyFormBasedPreventNavigation';
9
- import NewFormBasedPreventNavigation from './NewFormBasedPreventNavigation';
10
-
11
- interface Navigator extends BaseNavigator {
12
- block?: History['block'];
13
- location: Location;
14
- }
15
-
16
- type NavigationContextWithBlock = ContextType<typeof NavigationContext> & {
17
- navigator: Navigator;
18
- };
19
-
20
- export interface FormBasedPreventNavigationProps {
21
- ignoreLostChanges?: boolean;
22
- promptMessage?: string;
23
- }
24
-
25
- /** Prevent the user from navigating away from a form if there are any changes. */
26
- export default function FormBasedPreventNavigation({
27
- ignoreLostChanges,
28
- promptMessage = 'Changes you made may not be saved.',
29
- }: FormBasedPreventNavigationProps) {
30
- const { dirty, isSubmitting } = useFormikContext();
31
- const preventNavigate = !ignoreLostChanges && dirty && !isSubmitting;
32
-
33
- const { navigator } = useContext(
34
- NavigationContext
35
- ) as NavigationContextWithBlock;
36
-
37
- const isUsingDataRouter = navigator.location === undefined;
38
-
39
- if (isUsingDataRouter) {
40
- return (
41
- <NewFormBasedPreventNavigation
42
- promptMessage={promptMessage}
43
- preventNavigate={preventNavigate}
44
- navigator={navigator}
45
- />
46
- );
47
- } else {
48
- return (
49
- <LegacyFormBasedPreventNavigation
50
- promptMessage={promptMessage}
51
- preventNavigate={preventNavigate}
52
- navigator={navigator}
53
- />
54
- );
55
- }
56
- }
@@ -1,77 +0,0 @@
1
- import type { History, Blocker, Transition } from 'history';
2
- import { useEffect } from 'react';
3
- // see: https://gist.github.com/rmorse/426ffcc579922a82749934826fa9f743
4
- import { Navigator as BaseNavigator } from 'react-router-dom';
5
-
6
- interface Navigator extends BaseNavigator {
7
- block?: History['block'];
8
- }
9
-
10
- export interface FormBasedPreventNavigationProps {
11
- promptMessage?: string;
12
- preventNavigate: boolean;
13
- navigator: Navigator;
14
- }
15
- /** Only use this if the project uses `<BrowserRouter/>` or any router that does not support the new
16
- * [react-router Data API](https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis)
17
- *
18
- * Legacy function to prevent the user from navigating away from a form if there are any changes.
19
- */
20
- export default function LegacyFormBasedPreventNavigation({
21
- promptMessage = 'Changes you made may not be saved.',
22
- preventNavigate,
23
- navigator,
24
- }: FormBasedPreventNavigationProps) {
25
- useEffect(() => {
26
- if (!preventNavigate) {
27
- return;
28
- }
29
- let unblock = () => {};
30
- const push = navigator.push;
31
-
32
- // TODO: https://reactrouter.com/docs/en/v6/upgrading/v5#prompt-is-not-currently-supported
33
- // this is a workaround until we get native support for prompt on navigate
34
- if (navigator.block) {
35
- const blocker: Blocker = (tx) => {
36
- if (window.confirm(promptMessage)) {
37
- tx.retry();
38
- }
39
- };
40
- unblock = navigator.block((tx: Transition) => {
41
- const autoUnblockingTx = {
42
- ...tx,
43
- retry() {
44
- // Automatically unblock the transition so it can play all the way
45
- // through before retrying it. TODO: Figure out how to re-enable
46
- // this block if the transition is cancelled for some reason.
47
- unblock();
48
- tx.retry();
49
- },
50
- };
51
-
52
- blocker(autoUnblockingTx);
53
- });
54
- } else {
55
- //https://gist.github.com/MarksCode/64e438c82b0b2a1161e01c88ca0d0355
56
- navigator.push = (...args: Parameters<typeof push>) => {
57
- if (window.confirm(promptMessage)) {
58
- push(...args);
59
- }
60
- };
61
- }
62
-
63
- window.addEventListener('beforeunload', beforeUnload);
64
- return () => {
65
- unblock();
66
- navigator.push = push;
67
- window.removeEventListener('beforeunload', beforeUnload);
68
- };
69
-
70
- function beforeUnload(e: BeforeUnloadEvent) {
71
- e.preventDefault();
72
- e.returnValue = promptMessage;
73
- }
74
- }, [preventNavigate, promptMessage, navigator]);
75
-
76
- return null;
77
- }
@@ -1,59 +0,0 @@
1
- import type { History, Blocker, Transition } from 'history';
2
- import { useEffect } from 'react';
3
- import {
4
- Navigator as BaseNavigator,
5
- unstable_usePrompt as usePrompt,
6
- } from 'react-router-dom';
7
-
8
- interface Navigator extends BaseNavigator {
9
- block?: History['block'];
10
- location: Location;
11
- }
12
-
13
- interface FormBasedPreventNavigationProps {
14
- promptMessage?: string;
15
- preventNavigate: boolean;
16
- navigator: Navigator;
17
- }
18
-
19
- /** Temporary function to allow backwards compatibility with routers that do not use the new Data API */
20
- export default function NewFormBasedPreventNavigation({
21
- promptMessage = 'Changes you made may not be saved.',
22
- preventNavigate,
23
- navigator,
24
- }: FormBasedPreventNavigationProps) {
25
- usePrompt({
26
- when: preventNavigate,
27
- message: promptMessage,
28
- });
29
-
30
- // TODO: Once react-router fully supports usePrompt and when we do not want to support routers
31
- // that do not support the react-router Data API we can remove this.
32
- useEffect(() => {
33
- if (!preventNavigate) {
34
- return;
35
- }
36
- let unblock = () => {};
37
- const push = navigator.push;
38
-
39
- navigator.push = (...args: Parameters<typeof push>) => {
40
- if (window.confirm(promptMessage)) {
41
- push(...args);
42
- }
43
- };
44
-
45
- window.addEventListener('beforeunload', beforeUnload);
46
- return () => {
47
- unblock();
48
- navigator.push = push;
49
- window.removeEventListener('beforeunload', beforeUnload);
50
- };
51
-
52
- function beforeUnload(e: BeforeUnloadEvent) {
53
- e.preventDefault();
54
- e.returnValue = promptMessage;
55
- }
56
- }, [preventNavigate, promptMessage, navigator]);
57
-
58
- return null;
59
- }
@@ -1,18 +0,0 @@
1
- import React from 'react';
2
-
3
- export interface ServerErrors {
4
- [path: string]: string;
5
- }
6
- export interface ServerErrorContextProps {
7
- errors: ServerErrors;
8
- getError: (path: string) => string | undefined;
9
- setError: (path: string, errorMessage: string | undefined) => void;
10
- }
11
- /** Context to store the API errors from the server for the form. */
12
- export const ServerErrorContext = React.createContext<ServerErrorContextProps>({
13
- errors: {},
14
- getError: (path: string) => {
15
- return undefined;
16
- },
17
- setError: (path: string, errorMessage: string | undefined) => {},
18
- });
@@ -1,10 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`FormTestBase has matching snapshot 1`] = `
4
- <DocumentFragment>
5
- <form
6
- action="#"
7
- class="envoc-form-form"
8
- />
9
- </DocumentFragment>
10
- `;
@@ -1,47 +0,0 @@
1
- import { FormDefaults } from './FormDefaults';
2
- import { useFormikContext } from 'formik';
3
- import SubmitFormButton from './SubmitFormButton';
4
-
5
- export interface FormActionsProps {
6
- /** Allow the form to be submitted without any changes. By default this is not allowed. */
7
- allowPristineSubmit?: boolean;
8
- /** The cancel button's `onClick`.
9
- * @defaultValue `window.history.back()`
10
- */
11
- handleCancel?: () => void;
12
- /** Whether both buttons should be disabled. */
13
- disabled?: boolean;
14
- }
15
-
16
- /** Standard cancel and submit buttons. */
17
- export default function FormActions({
18
- allowPristineSubmit,
19
- handleCancel,
20
- disabled,
21
- }: FormActionsProps) {
22
- const { isSubmitting } = useFormikContext();
23
- return (
24
- <>
25
- <SubmitFormButton
26
- className={FormDefaults.cssClassPrefix + 'form-actions'}
27
- allowPristineSubmit={allowPristineSubmit}
28
- disabled={disabled}
29
- />
30
- <button
31
- type="button"
32
- className={
33
- FormDefaults.cssClassPrefix +
34
- 'form-actions ' +
35
- FormDefaults.cssClassPrefix +
36
- 'cancel-form-button'
37
- }
38
- disabled={isSubmitting || disabled}
39
- onClick={handleCancel || goBack}>
40
- Cancel
41
- </button>
42
- </>
43
- );
44
- function goBack() {
45
- window.history.back();
46
- }
47
- }
@@ -1,2 +0,0 @@
1
- /** `envoc-form-` CSS class prefix */
2
- export const FormDefaults = { cssClassPrefix: 'envoc-form-' };
package/src/Group.tsx DELETED
@@ -1,62 +0,0 @@
1
- import classNames from 'classnames';
2
- import { FormDefaults } from './FormDefaults';
3
- import FieldErrorScrollTarget from './Field/FieldErrorScrollTarget';
4
- import { InjectedFieldProps } from './Field/InjectedFieldProps';
5
-
6
- export interface GroupProps extends InjectedFieldProps<any> {
7
- /** Extra class names to apply. */
8
- className?: string;
9
-
10
- children: React.ReactNode;
11
-
12
- /** Simple text label before the input. */
13
- label?: string;
14
-
15
- /** Simple helper text after the input. */
16
- helpText?: string | React.ReactNode;
17
-
18
- /** Whether the field should be disabled. */
19
- disabled?: boolean;
20
-
21
- required?: boolean;
22
- }
23
-
24
- /** Contains standard field bits like a label, helper text, error scroll target, validation message container, etc. */
25
- export default function Group({
26
- className,
27
- children,
28
- label,
29
- helpText,
30
- meta,
31
- input,
32
- disabled,
33
- required,
34
- }: GroupProps) {
35
- return (
36
- <div
37
- className={classNames(className, FormDefaults.cssClassPrefix + 'group', {
38
- [FormDefaults.cssClassPrefix + 'invalid']: meta.error,
39
- [FormDefaults.cssClassPrefix + 'disabled']: disabled,
40
- [FormDefaults.cssClassPrefix + 'required']: required,
41
- })}>
42
- <FieldErrorScrollTarget />
43
- {meta.warning && (
44
- <div className={FormDefaults.cssClassPrefix + 'warning'}>
45
- {meta.warning}
46
- </div>
47
- )}
48
- <label htmlFor={input.id}>{label}</label>
49
- {children}
50
- {meta.error && (
51
- <div
52
- id={`${input.id}-error`}
53
- className={FormDefaults.cssClassPrefix + 'error'}>
54
- {meta.error}
55
- </div>
56
- )}
57
- {helpText && (
58
- <div className={FormDefaults.cssClassPrefix + 'help'}>{helpText}</div>
59
- )}
60
- </div>
61
- );
62
- }