envoc-form 3.3.0 → 4.0.1-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/css/envoc-form-styles.css +0 -113
- package/dist/css/envoc-form-styles.css.map +1 -1
- package/es/AddressInput/AddressInput.d.ts +15 -0
- package/es/AddressInput/AddressInput.js +21 -97
- package/es/AddressInput/UsStates.d.ts +3 -0
- package/es/AddressInput/UsStates.js +53 -152
- package/es/ConfirmBaseForm/ConfirmBaseForm.d.ts +10 -0
- package/es/ConfirmBaseForm/ConfirmBaseForm.js +35 -43
- package/es/ConfirmDeleteForm/ConfirmDeleteForm.d.ts +11 -0
- package/es/ConfirmDeleteForm/ConfirmDeleteForm.js +54 -40
- package/es/DatePickerInput/DatePickerInput.d.ts +14 -0
- package/es/DatePickerInput/DatePickerInput.js +63 -95
- package/es/Field/CustomFieldInputProps.d.ts +7 -0
- package/es/Field/CustomFieldInputProps.js +1 -0
- package/es/Field/CustomFieldMetaProps.d.ts +4 -0
- package/es/Field/CustomFieldMetaProps.js +1 -0
- package/es/Field/Field.d.ts +22 -0
- package/es/Field/Field.js +46 -0
- package/es/Field/FieldErrorScrollTarget.d.ts +2 -0
- package/es/Field/FieldErrorScrollTarget.js +11 -0
- package/es/Field/FieldNameContext.d.ts +3 -0
- package/es/Field/FieldNameContext.js +3 -0
- package/es/Field/FieldSection.d.ts +7 -0
- package/es/Field/FieldSection.js +20 -0
- package/es/Field/InjectedFieldProps.d.ts +7 -0
- package/es/Field/InjectedFieldProps.js +1 -0
- package/es/Field/useStandardField.d.ts +15 -0
- package/es/Field/useStandardField.js +93 -0
- package/es/FieldArray/FieldArray.d.ts +15 -0
- package/es/FieldArray/FieldArray.js +80 -0
- package/es/File/FileGroup.d.ts +8 -0
- package/es/File/FileGroup.js +50 -0
- package/es/File/FileList.d.ts +6 -0
- package/es/File/FileList.js +20 -0
- package/es/File/humanFileSize.d.ts +1 -0
- package/es/File/humanFileSize.js +6 -0
- package/es/Form/FocusError.d.ts +5 -0
- package/es/Form/FocusError.js +41 -53
- package/es/Form/Form.d.ts +22 -0
- package/es/Form/Form.js +111 -125
- package/es/Form/FormBasedPreventNavigation.d.ts +5 -0
- package/es/Form/FormBasedPreventNavigation.js +53 -30
- package/es/Form/ServerErrorContext.d.ts +10 -0
- package/es/Form/ServerErrorContext.js +8 -6
- package/es/FormActions.d.ts +7 -0
- package/es/FormActions.js +22 -0
- package/es/Group.d.ts +13 -0
- package/es/Group.js +22 -0
- package/es/Input/IconInputGroup.d.ts +9 -0
- package/es/Input/IconInputGroup.js +40 -0
- package/es/Input/InputGroup.d.ts +12 -0
- package/es/Input/InputGroup.js +33 -0
- package/es/Input/MoneyInputGroup.d.ts +7 -0
- package/es/Input/MoneyInputGroup.js +41 -0
- package/es/Input/NumberInputGroup.d.ts +7 -0
- package/es/Input/NumberInputGroup.js +41 -0
- package/es/Input/StringInputGroup.d.ts +7 -0
- package/es/Input/StringInputGroup.js +40 -0
- package/es/Normalization/NormalizationFunction.d.ts +4 -0
- package/es/Normalization/NormalizationFunction.js +1 -0
- package/es/Normalization/normalizers.d.ts +2 -0
- package/es/Normalization/normalizers.js +30 -0
- package/es/Select/BooleanSelectGroup.d.ts +7 -0
- package/es/Select/BooleanSelectGroup.js +27 -0
- package/es/Select/NumberSelectGroup.d.ts +8 -0
- package/es/Select/NumberSelectGroup.js +19 -0
- package/es/Select/SelectGroup.d.ts +22 -0
- package/es/Select/SelectGroup.js +59 -0
- package/es/Select/SelectGroupPropsHelper.d.ts +3 -0
- package/es/Select/SelectGroupPropsHelper.js +1 -0
- package/es/Select/StringSelectGroup.d.ts +8 -0
- package/es/Select/StringSelectGroup.js +19 -0
- package/es/StandardFormActions.d.ts +6 -0
- package/es/StandardFormActions.js +23 -24
- package/es/SubmitFormButton.d.ts +7 -0
- package/es/SubmitFormButton.js +37 -23
- package/es/Validation/ValidatedApiResult.d.ts +6 -0
- package/es/Validation/ValidatedApiResult.js +1 -0
- package/es/Validation/ValidationError.d.ts +5 -0
- package/es/Validation/ValidationError.js +1 -0
- package/es/Validation/ValidationFunction.d.ts +4 -0
- package/es/Validation/ValidationFunction.js +1 -0
- package/es/Validation/validators.d.ts +15 -0
- package/es/Validation/validators.js +73 -0
- package/es/__Tests__/FormTestBase.d.ts +27 -0
- package/es/__Tests__/FormTestBase.js +83 -12
- package/{src/__Tests__/index.js → es/__Tests__/index.d.ts} +0 -0
- package/es/__Tests__/index.js +2 -2
- package/es/index.d.ts +57 -0
- package/es/index.js +41 -25
- package/es/utils/objectContainsNonSerializableProperty.d.ts +1 -0
- package/es/utils/objectContainsNonSerializableProperty.js +14 -16
- package/es/utils/objectToFormData.d.ts +10 -0
- package/es/utils/objectToFormData.js +77 -65
- package/es/utils/typeChecks.d.ts +8 -0
- package/es/utils/typeChecks.js +18 -25
- package/lib/AddressInput/AddressInput.d.ts +15 -0
- package/lib/AddressInput/AddressInput.js +27 -123
- package/lib/AddressInput/UsStates.d.ts +3 -0
- package/lib/AddressInput/UsStates.js +55 -159
- package/lib/ConfirmBaseForm/ConfirmBaseForm.d.ts +10 -0
- package/lib/ConfirmBaseForm/ConfirmBaseForm.js +41 -57
- package/lib/ConfirmDeleteForm/ConfirmDeleteForm.d.ts +11 -0
- package/lib/ConfirmDeleteForm/ConfirmDeleteForm.js +60 -56
- package/lib/DatePickerInput/DatePickerInput.d.ts +14 -0
- package/lib/DatePickerInput/DatePickerInput.js +69 -113
- package/lib/Field/CustomFieldInputProps.d.ts +7 -0
- package/lib/Field/CustomFieldInputProps.js +2 -0
- package/lib/Field/CustomFieldMetaProps.d.ts +4 -0
- package/lib/Field/CustomFieldMetaProps.js +2 -0
- package/lib/Field/Field.d.ts +22 -0
- package/lib/Field/Field.js +51 -0
- package/lib/Field/FieldErrorScrollTarget.d.ts +2 -0
- package/lib/Field/FieldErrorScrollTarget.js +14 -0
- package/lib/Field/FieldNameContext.d.ts +3 -0
- package/lib/Field/FieldNameContext.js +9 -0
- package/lib/Field/FieldSection.d.ts +7 -0
- package/lib/Field/FieldSection.js +23 -0
- package/lib/Field/InjectedFieldProps.d.ts +7 -0
- package/lib/Field/InjectedFieldProps.js +2 -0
- package/lib/Field/useStandardField.d.ts +15 -0
- package/lib/Field/useStandardField.js +96 -0
- package/lib/FieldArray/FieldArray.d.ts +15 -0
- package/lib/FieldArray/FieldArray.js +86 -0
- package/lib/File/FileGroup.d.ts +8 -0
- package/lib/File/FileGroup.js +55 -0
- package/lib/File/FileList.d.ts +6 -0
- package/lib/File/FileList.js +23 -0
- package/lib/File/humanFileSize.d.ts +1 -0
- package/lib/File/humanFileSize.js +10 -0
- package/lib/Form/FocusError.d.ts +5 -0
- package/lib/Form/FocusError.js +47 -66
- package/lib/Form/Form.d.ts +22 -0
- package/lib/Form/Form.js +117 -153
- package/lib/Form/FormBasedPreventNavigation.d.ts +5 -0
- package/lib/Form/FormBasedPreventNavigation.js +56 -39
- package/lib/Form/ServerErrorContext.d.ts +10 -0
- package/lib/Form/ServerErrorContext.js +14 -18
- package/lib/FormActions.d.ts +7 -0
- package/lib/FormActions.js +28 -0
- package/lib/Group.d.ts +13 -0
- package/lib/Group.js +28 -0
- package/lib/Input/IconInputGroup.d.ts +9 -0
- package/lib/Input/IconInputGroup.js +45 -0
- package/lib/Input/InputGroup.d.ts +12 -0
- package/lib/Input/InputGroup.js +38 -0
- package/lib/Input/MoneyInputGroup.d.ts +7 -0
- package/lib/Input/MoneyInputGroup.js +46 -0
- package/lib/Input/NumberInputGroup.d.ts +7 -0
- package/lib/Input/NumberInputGroup.js +46 -0
- package/lib/Input/StringInputGroup.d.ts +7 -0
- package/lib/Input/StringInputGroup.js +45 -0
- package/lib/Normalization/NormalizationFunction.d.ts +4 -0
- package/lib/Normalization/NormalizationFunction.js +2 -0
- package/lib/Normalization/normalizers.d.ts +2 -0
- package/lib/Normalization/normalizers.js +35 -0
- package/lib/Select/BooleanSelectGroup.d.ts +7 -0
- package/lib/Select/BooleanSelectGroup.js +34 -0
- package/lib/Select/NumberSelectGroup.d.ts +8 -0
- package/lib/Select/NumberSelectGroup.js +27 -0
- package/lib/Select/SelectGroup.d.ts +22 -0
- package/lib/Select/SelectGroup.js +65 -0
- package/lib/Select/SelectGroupPropsHelper.d.ts +3 -0
- package/lib/Select/SelectGroupPropsHelper.js +2 -0
- package/lib/Select/StringSelectGroup.d.ts +8 -0
- package/lib/Select/StringSelectGroup.js +27 -0
- package/lib/StandardFormActions.d.ts +6 -0
- package/lib/StandardFormActions.js +29 -37
- package/lib/SubmitFormButton.d.ts +7 -0
- package/lib/SubmitFormButton.js +42 -38
- package/lib/Validation/ValidatedApiResult.d.ts +6 -0
- package/lib/Validation/ValidatedApiResult.js +2 -0
- package/lib/Validation/ValidationError.d.ts +5 -0
- package/lib/Validation/ValidationError.js +2 -0
- package/lib/Validation/ValidationFunction.d.ts +4 -0
- package/lib/Validation/ValidationFunction.js +2 -0
- package/lib/Validation/validators.d.ts +15 -0
- package/lib/Validation/validators.js +86 -0
- package/lib/__Tests__/FormTestBase.d.ts +27 -0
- package/lib/__Tests__/FormTestBase.js +86 -25
- package/lib/__Tests__/index.d.ts +2 -0
- package/lib/__Tests__/index.js +8 -15
- package/lib/index.d.ts +57 -0
- package/lib/index.js +101 -262
- package/lib/utils/objectContainsNonSerializableProperty.d.ts +1 -0
- package/lib/utils/objectContainsNonSerializableProperty.js +17 -24
- package/lib/utils/objectToFormData.d.ts +10 -0
- package/lib/utils/objectToFormData.js +79 -73
- package/lib/utils/typeChecks.d.ts +8 -0
- package/lib/utils/typeChecks.js +29 -58
- package/package.json +106 -101
- package/src/AddressInput/{AddesssInput.test.js → AddressInput.test.tsx} +7 -3
- package/src/AddressInput/AddressInput.tsx +72 -0
- package/src/AddressInput/{UsStates.js → UsStates.ts} +3 -1
- package/src/AddressInput/__snapshots__/AddressInput.test.tsx.snap +175 -0
- package/src/ConfirmBaseForm/ConfirmBaseForm.test.tsx +24 -0
- package/src/ConfirmBaseForm/ConfirmBaseForm.tsx +50 -0
- package/src/ConfirmBaseForm/__snapshots__/{ConfirmBaseForm.test.js.snap → ConfirmBaseForm.test.tsx.snap} +2 -2
- package/src/ConfirmDeleteForm/{ConfirmDeleteForm.test.js → ConfirmDeleteForm.test.tsx} +3 -3
- package/src/ConfirmDeleteForm/ConfirmDeleteForm.tsx +67 -0
- package/src/ConfirmDeleteForm/__snapshots__/{ConfirmDeleteForm.test.js.snap → ConfirmDeleteForm.test.tsx.snap} +2 -2
- package/src/DatePickerInput/DatePickerInput.test.tsx +48 -0
- package/src/DatePickerInput/DatePickerInput.tsx +85 -0
- package/src/DatePickerInput/__snapshots__/DatePickerInput.test.tsx.snap +151 -0
- package/src/Field/CustomFieldInputProps.ts +10 -0
- package/src/Field/CustomFieldMetaProps.ts +5 -0
- package/src/Field/Field.tsx +90 -0
- package/src/Field/FieldErrorScrollTarget.tsx +11 -0
- package/src/Field/FieldNameContext.ts +6 -0
- package/src/Field/FieldSection.tsx +18 -0
- package/src/Field/InjectedFieldProps.ts +8 -0
- package/src/Field/useStandardField.ts +121 -0
- package/src/FieldArray/FieldArray.tsx +133 -0
- package/src/File/FileGroup.test.tsx +35 -0
- package/src/File/FileGroup.tsx +71 -0
- package/src/File/FileList.tsx +19 -0
- package/src/File/__snapshots__/FileGroup.test.tsx.snap +32 -0
- package/src/File/humanFileSize.ts +8 -0
- package/src/Form/{FocusError.js → FocusError.tsx} +10 -6
- package/src/Form/Form.test.tsx +14 -0
- package/src/Form/{Form.js → Form.tsx} +71 -31
- package/src/Form/FormBasedPreventNavigation.tsx +74 -0
- package/src/Form/ServerErrorContext.ts +17 -0
- package/src/Form/__snapshots__/{Form.test.js.snap → Form.test.tsx.snap} +1 -1
- package/src/FormActions.tsx +34 -0
- package/src/Group.tsx +43 -0
- package/src/Input/IconInputGroup.tsx +48 -0
- package/src/Input/InputGroup.tsx +57 -0
- package/src/Input/MoneyInputGroup.tsx +44 -0
- package/src/Input/NumberInputGroup.tsx +42 -0
- package/src/Input/StringInputGroup.tsx +40 -0
- package/src/Input/__Tests__/IconInputGroup.test.tsx +35 -0
- package/src/Input/__Tests__/MoneyInputGroup.test.tsx +37 -0
- package/src/Input/__Tests__/NumberInputGroup.test.tsx +35 -0
- package/src/Input/__Tests__/StringInputGroup.test.tsx +27 -0
- package/src/Input/__Tests__/__snapshots__/IconInputGroup.test.tsx.snap +29 -0
- package/src/Input/__Tests__/__snapshots__/MoneyInputGroup.test.tsx.snap +31 -0
- package/src/Input/__Tests__/__snapshots__/NumberInputGroup.test.tsx.snap +29 -0
- package/src/Input/__Tests__/__snapshots__/StringInputGroup.test.tsx.snap +28 -0
- package/src/Normalization/NormalizationFunction.ts +4 -0
- package/src/{normalizers.js → Normalization/normalizers.ts} +5 -5
- package/src/Select/BooleanSelectGroup.tsx +27 -0
- package/src/Select/NumberSelectGroup.tsx +14 -0
- package/src/Select/SelectGroup.tsx +106 -0
- package/src/Select/SelectGroupPropsHelper.ts +4 -0
- package/src/Select/StringSelectGroup.tsx +14 -0
- package/src/Select/__tests__/BooleanSelectGroup.test.tsx +35 -0
- package/src/Select/__tests__/NumberSelectGroup.test.tsx +87 -0
- package/src/Select/__tests__/StringSelectGroup.test.tsx +89 -0
- package/src/Select/__tests__/__snapshots__/BooleanSelectGroup.test.tsx.snap +99 -0
- package/src/Select/__tests__/__snapshots__/NumberSelectGroup.test.tsx.snap +197 -0
- package/src/Select/__tests__/__snapshots__/StringSelectGroup.test.tsx.snap +197 -0
- package/src/{StandardFormActions.js → StandardFormActions.tsx} +12 -6
- package/src/SubmitFormButton.tsx +44 -0
- package/src/Validation/ValidatedApiResult.ts +8 -0
- package/src/Validation/ValidationError.ts +6 -0
- package/src/Validation/ValidationFunction.ts +4 -0
- package/src/{validators/validators.test.js → Validation/validators.test.tsx} +6 -4
- package/src/Validation/validators.ts +92 -0
- package/src/__Tests__/FormTestBase.tsx +63 -0
- package/src/__Tests__/{StandardFormActions.test.js → StandardFormActions.test.tsx} +2 -8
- package/src/__Tests__/{SubmitFormButton.test.js → SubmitFormButton.test.tsx} +2 -8
- package/src/__Tests__/__snapshots__/{StandardFormActions.test.js.snap → StandardFormActions.test.tsx.snap} +2 -2
- package/src/__Tests__/__snapshots__/{SubmitFormButton.test.js.snap → SubmitFormButton.test.tsx.snap} +1 -1
- package/src/__Tests__/index.ts +3 -0
- package/src/index.ts +114 -0
- package/src/react-app-env.d.ts +1 -0
- package/src/styles.scss +0 -7
- package/src/utils/{objectContainsNonSerializableProperty.test.js → objectContainsNonSerializableProperty.test.tsx} +0 -0
- package/src/utils/{objectContainsNonSerializableProperty.js → objectContainsNonSerializableProperty.ts} +4 -2
- package/src/utils/{objectToFormData.test.js → objectToFormData.test.tsx} +0 -0
- package/src/utils/{objectToFormData.js → objectToFormData.ts} +29 -13
- package/src/utils/typeChecks.ts +18 -0
- package/es/AddressInput/index.js +0 -3
- package/es/BoolInput/BoolInput.js +0 -10
- package/es/BoolInput/InlineBoolInput.js +0 -10
- package/es/BoolInput/boolOptions.js +0 -8
- package/es/BoolInput/index.js +0 -3
- package/es/ConfirmBaseForm/index.js +0 -2
- package/es/ConfirmDeleteForm/index.js +0 -2
- package/es/DatePickerInput/index.js +0 -2
- package/es/ErrorScrollTarget.js +0 -10
- package/es/FileInput/DefaultFileList.js +0 -36
- package/es/FileInput/DropzoneFileInput.js +0 -58
- package/es/FileInput/FileInput.js +0 -62
- package/es/FileInput/index.js +0 -4
- package/es/Form/index.js +0 -5
- package/es/FormGroup.js +0 -22
- package/es/FormGroupWrapper.js +0 -22
- package/es/FormInput/FormInput.js +0 -212
- package/es/FormInput/index.js +0 -2
- package/es/FormInputArray/FormInputArray.js +0 -225
- package/es/FormInputArray/index.js +0 -2
- package/es/FormSection.js +0 -11
- package/es/IconInput.js +0 -33
- package/es/InlineFormInput/InlineFormInput.js +0 -8
- package/es/InlineFormInput/index.js +0 -2
- package/es/MoneyFormattedInput/MoneyFormattedInput.js +0 -106
- package/es/MoneyFormattedInput/index.js +0 -2
- package/es/MoneyInput/InlineMoneyInput.js +0 -7
- package/es/MoneyInput/MoneyInput.js +0 -7
- package/es/MoneyInput/index.js +0 -3
- package/es/MoneyInput/moneyInputProps.js +0 -13
- package/es/NestedFormFieldContext.js +0 -4
- package/es/ReactSelectField/ReactSelectField.js +0 -162
- package/es/ReactSelectField/index.js +0 -2
- package/es/normalizers.js +0 -39
- package/es/selectors.js +0 -6
- package/es/useStandardFormInput.js +0 -119
- package/es/utils/index.js +0 -3
- package/es/validators/index.js +0 -2
- package/es/validators/validators.js +0 -94
- package/lib/AddressInput/index.js +0 -23
- package/lib/BoolInput/BoolInput.js +0 -23
- package/lib/BoolInput/InlineBoolInput.js +0 -23
- package/lib/BoolInput/boolOptions.js +0 -15
- package/lib/BoolInput/index.js +0 -23
- package/lib/ConfirmBaseForm/index.js +0 -13
- package/lib/ConfirmDeleteForm/index.js +0 -13
- package/lib/DatePickerInput/index.js +0 -13
- package/lib/ErrorScrollTarget.js +0 -20
- package/lib/FileInput/DefaultFileList.js +0 -47
- package/lib/FileInput/DropzoneFileInput.js +0 -75
- package/lib/FileInput/FileInput.js +0 -82
- package/lib/FileInput/index.js +0 -31
- package/lib/Form/index.js +0 -39
- package/lib/FormGroup.js +0 -33
- package/lib/FormGroupWrapper.js +0 -37
- package/lib/FormInput/FormInput.js +0 -236
- package/lib/FormInput/index.js +0 -13
- package/lib/FormInputArray/FormInputArray.js +0 -248
- package/lib/FormInputArray/index.js +0 -13
- package/lib/FormSection.js +0 -28
- package/lib/IconInput.js +0 -51
- package/lib/InlineFormInput/InlineFormInput.js +0 -20
- package/lib/InlineFormInput/index.js +0 -13
- package/lib/MoneyFormattedInput/MoneyFormattedInput.js +0 -126
- package/lib/MoneyFormattedInput/index.js +0 -15
- package/lib/MoneyInput/InlineMoneyInput.js +0 -20
- package/lib/MoneyInput/MoneyInput.js +0 -20
- package/lib/MoneyInput/index.js +0 -23
- package/lib/MoneyInput/moneyInputProps.js +0 -26
- package/lib/NestedFormFieldContext.js +0 -16
- package/lib/ReactSelectField/ReactSelectField.js +0 -187
- package/lib/ReactSelectField/index.js +0 -31
- package/lib/normalizers.js +0 -51
- package/lib/selectors.js +0 -18
- package/lib/useStandardFormInput.js +0 -135
- package/lib/utils/index.js +0 -23
- package/lib/validators/index.js +0 -17
- package/lib/validators/validators.js +0 -130
- package/src/AddressInput/AddressInput.js +0 -73
- package/src/AddressInput/__snapshots__/AddesssInput.test.js.snap +0 -207
- package/src/AddressInput/index.js +0 -3
- package/src/BoolInput/BoolInput.js +0 -7
- package/src/BoolInput/BoolInput.test.js +0 -23
- package/src/BoolInput/InlineBoolInput.js +0 -7
- package/src/BoolInput/__snapshots__/BoolInput.test.js.snap +0 -89
- package/src/BoolInput/boolOptions.js +0 -6
- package/src/BoolInput/index.js +0 -4
- package/src/ConfirmBaseForm/ConfirmBaseForm.js +0 -37
- package/src/ConfirmBaseForm/ConfirmBaseForm.test.js +0 -14
- package/src/ConfirmBaseForm/index.js +0 -2
- package/src/ConfirmDeleteForm/ConfirmDeleteForm.js +0 -39
- package/src/ConfirmDeleteForm/index.js +0 -2
- package/src/DatePickerInput/DatePickerInput.js +0 -49
- package/src/DatePickerInput/DatePickerInput.test.js +0 -74
- package/src/DatePickerInput/__snapshots__/DatePickerInput.test.js.snap +0 -134
- package/src/DatePickerInput/date-picker-input.scss +0 -42
- package/src/DatePickerInput/index.js +0 -3
- package/src/ErrorScrollTarget.js +0 -6
- package/src/FileInput/DefaultFileList.js +0 -39
- package/src/FileInput/DropzoneFileInput.js +0 -56
- package/src/FileInput/DropzoneFileInput.test.js +0 -24
- package/src/FileInput/FileInput.js +0 -77
- package/src/FileInput/FileInput.test.js +0 -24
- package/src/FileInput/__snapshots__/DropzoneFileInput.test.js.snap +0 -57
- package/src/FileInput/__snapshots__/FileInput.test.js.snap +0 -58
- package/src/FileInput/file-input.scss +0 -58
- package/src/FileInput/index.js +0 -5
- package/src/Form/Form.test.js +0 -23
- package/src/Form/FormBasedPreventNavigation.js +0 -25
- package/src/Form/ServerErrorContext.js +0 -7
- package/src/Form/index.js +0 -11
- package/src/FormGroup.js +0 -30
- package/src/FormGroupWrapper.js +0 -28
- package/src/FormInput/FormInput.js +0 -148
- package/src/FormInput/FormInput.test.js +0 -66
- package/src/FormInput/__snapshots__/FormInput.test.js.snap +0 -323
- package/src/FormInput/form-input.scss +0 -9
- package/src/FormInput/index.js +0 -2
- package/src/FormInputArray/FormInputArray.js +0 -224
- package/src/FormInputArray/FormInputArray.test.js +0 -108
- package/src/FormInputArray/__snapshots__/FormInputArray.test.js.snap +0 -52
- package/src/FormInputArray/form-input-array.scss +0 -13
- package/src/FormInputArray/index.js +0 -2
- package/src/FormSection.js +0 -13
- package/src/IconInput.js +0 -31
- package/src/InlineFormInput/InlineFormInput.js +0 -6
- package/src/InlineFormInput/InlineFormInput.test.js +0 -23
- package/src/InlineFormInput/__snapshots__/InlineFormInput.test.js.snap +0 -26
- package/src/InlineFormInput/index.js +0 -3
- package/src/InlineFormInput/inline-form-input.scss +0 -3
- package/src/MoneyFormattedInput/MoneyFormattedInput.js +0 -115
- package/src/MoneyFormattedInput/index.js +0 -3
- package/src/MoneyInput/InlineMoneyInput.js +0 -7
- package/src/MoneyInput/MoneyInput.js +0 -7
- package/src/MoneyInput/MoneyInputs.test.js +0 -43
- package/src/MoneyInput/__snapshots__/MoneyInputs.test.js.snap +0 -81
- package/src/MoneyInput/index.js +0 -4
- package/src/MoneyInput/money-input.scss +0 -3
- package/src/MoneyInput/moneyInputProps.js +0 -12
- package/src/NestedFormFieldContext.js +0 -6
- package/src/ReactSelectField/ReactSelectField.js +0 -155
- package/src/ReactSelectField/index.js +0 -6
- package/src/ReactSelectField/react-select-field.scss +0 -5
- package/src/SubmitFormButton.js +0 -28
- package/src/__Tests__/FormTestBase.js +0 -14
- package/src/__Tests__/IconInput.test.js +0 -23
- package/src/__Tests__/__snapshots__/IconInput.test.js.snap +0 -38
- package/src/index.js +0 -70
- package/src/selectors.js +0 -3
- package/src/useStandardFormInput.js +0 -118
- package/src/utils/index.js +0 -3
- package/src/utils/typeChecks.js +0 -18
- package/src/validators/index.js +0 -2
- package/src/validators/validators.js +0 -93
@@ -7,13 +7,13 @@ exports[`ConfirmBaseForm has matching snapshot 1`] = `
|
|
7
7
|
>
|
8
8
|
<h3 />
|
9
9
|
<button
|
10
|
-
class="
|
10
|
+
class="confirm-base-form-yes-button"
|
11
11
|
type="button"
|
12
12
|
>
|
13
13
|
Yes
|
14
14
|
</button>
|
15
15
|
<button
|
16
|
-
class="
|
16
|
+
class="confirm-base-form-cancel-button"
|
17
17
|
type="button"
|
18
18
|
>
|
19
19
|
Cancel
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { HashRouter } from 'react-router-dom';
|
3
|
-
import { render
|
3
|
+
import { render } from '@testing-library/react';
|
4
4
|
|
5
5
|
import ConfirmDeleteForm from './ConfirmDeleteForm';
|
6
6
|
|
@@ -8,7 +8,7 @@ describe('ConfirmDeleteForm', () => {
|
|
8
8
|
it('Renders without error', () => {
|
9
9
|
render(
|
10
10
|
<HashRouter>
|
11
|
-
<ConfirmDeleteForm />
|
11
|
+
<ConfirmDeleteForm form="foo" />
|
12
12
|
</HashRouter>
|
13
13
|
);
|
14
14
|
});
|
@@ -16,7 +16,7 @@ describe('ConfirmDeleteForm', () => {
|
|
16
16
|
it('has matching snapshot', () => {
|
17
17
|
const renderResult = render(
|
18
18
|
<HashRouter>
|
19
|
-
<ConfirmDeleteForm />
|
19
|
+
<ConfirmDeleteForm form="foo" />
|
20
20
|
</HashRouter>
|
21
21
|
);
|
22
22
|
expect(renderResult.asFragment()).toMatchSnapshot();
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { useNavigate, useParams } from 'react-router-dom';
|
3
|
+
import { toast } from 'react-toastify';
|
4
|
+
import { useAxiosRequestProps } from 'envoc-request';
|
5
|
+
import ConfirmBaseForm, { ConfirmBaseFormProps } from '../ConfirmBaseForm/ConfirmBaseForm';
|
6
|
+
|
7
|
+
export interface ConfirmDeleteFormProps
|
8
|
+
extends Pick<ConfirmBaseFormProps, 'style'> {
|
9
|
+
successUrl?: string;
|
10
|
+
form: string;
|
11
|
+
title?: string;
|
12
|
+
handleComplete?: Function;
|
13
|
+
handleError?: Function;
|
14
|
+
children?: React.ReactNode;
|
15
|
+
}
|
16
|
+
|
17
|
+
export default function ConfirmDeleteForm({
|
18
|
+
successUrl,
|
19
|
+
form,
|
20
|
+
title,
|
21
|
+
handleComplete,
|
22
|
+
handleError,
|
23
|
+
children,
|
24
|
+
...props
|
25
|
+
}: ConfirmDeleteFormProps) {
|
26
|
+
const navigate = useNavigate();
|
27
|
+
const { entityId } = useParams();
|
28
|
+
const onComplete =
|
29
|
+
handleComplete ??
|
30
|
+
function () {
|
31
|
+
toast.success('Deleted!');
|
32
|
+
goBack();
|
33
|
+
};
|
34
|
+
const onError =
|
35
|
+
handleError ??
|
36
|
+
function (error: any) {
|
37
|
+
toast.error(
|
38
|
+
error.response?.data?.validationFailures[0]?.errorMessage ??
|
39
|
+
'Something went wrong talking to the portal. Contact support if this continues.'
|
40
|
+
);
|
41
|
+
};
|
42
|
+
|
43
|
+
const request = {
|
44
|
+
method: 'delete',
|
45
|
+
url: `/api/${form}/${entityId}`,
|
46
|
+
onComplete: onComplete,
|
47
|
+
onError: onError,
|
48
|
+
} as useAxiosRequestProps;
|
49
|
+
|
50
|
+
return (
|
51
|
+
<ConfirmBaseForm
|
52
|
+
request={request}
|
53
|
+
handleCancel={goBack}
|
54
|
+
title={title ?? 'Are you sure you want to delete this?'}
|
55
|
+
{...props}>
|
56
|
+
{children}
|
57
|
+
</ConfirmBaseForm>
|
58
|
+
);
|
59
|
+
|
60
|
+
function goBack() {
|
61
|
+
if (successUrl) {
|
62
|
+
navigate(successUrl);
|
63
|
+
} else {
|
64
|
+
navigate(-1);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
@@ -9,13 +9,13 @@ exports[`ConfirmDeleteForm has matching snapshot 1`] = `
|
|
9
9
|
Are you sure you want to delete this?
|
10
10
|
</h3>
|
11
11
|
<button
|
12
|
-
class="
|
12
|
+
class="confirm-base-form-yes-button"
|
13
13
|
type="button"
|
14
14
|
>
|
15
15
|
Yes
|
16
16
|
</button>
|
17
17
|
<button
|
18
|
-
class="
|
18
|
+
class="confirm-base-form-cancel-button"
|
19
19
|
type="button"
|
20
20
|
>
|
21
21
|
Cancel
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render } from '@testing-library/react';
|
3
|
+
import DatePickerInput from './DatePickerInput';
|
4
|
+
import FormTestBase from '../__Tests__/FormTestBase';
|
5
|
+
|
6
|
+
//hack so the datepicker internals don't complain about this not existing in the context of jest
|
7
|
+
HTMLCanvasElement.prototype.getContext = () => {};
|
8
|
+
|
9
|
+
describe('IconInputGroup', () => {
|
10
|
+
it('renders without crashing', () => {
|
11
|
+
render(
|
12
|
+
<FormTestBase>
|
13
|
+
{({ Field }) => (
|
14
|
+
<Field
|
15
|
+
name="favoriteDate"
|
16
|
+
Component={DatePickerInput}
|
17
|
+
label="Favorite Date"
|
18
|
+
monthPlaceholder="mm"
|
19
|
+
dayPlaceholder="dd"
|
20
|
+
yearPlaceholder="yyyy"
|
21
|
+
maxDate={new Date('9/23/2023')}
|
22
|
+
minDate={new Date('6/22/2022')}
|
23
|
+
/>
|
24
|
+
)}
|
25
|
+
</FormTestBase>
|
26
|
+
);
|
27
|
+
});
|
28
|
+
|
29
|
+
it('has matching snapshot', () => {
|
30
|
+
const renderResult = render(
|
31
|
+
<FormTestBase>
|
32
|
+
{({ Field }) => (
|
33
|
+
<Field
|
34
|
+
name="favoriteDate"
|
35
|
+
Component={DatePickerInput}
|
36
|
+
label="Favorite Date"
|
37
|
+
monthPlaceholder="mm"
|
38
|
+
dayPlaceholder="dd"
|
39
|
+
yearPlaceholder="yyyy"
|
40
|
+
maxDate={new Date('9/23/2023')}
|
41
|
+
minDate={new Date('6/22/2022')}
|
42
|
+
/>
|
43
|
+
)}
|
44
|
+
</FormTestBase>
|
45
|
+
);
|
46
|
+
expect(renderResult.asFragment()).toMatchSnapshot();
|
47
|
+
});
|
48
|
+
});
|
@@ -0,0 +1,85 @@
|
|
1
|
+
import { useState } from 'react';
|
2
|
+
import DatePicker, { DatePickerProps } from 'react-date-picker';
|
3
|
+
import classnames from 'classnames';
|
4
|
+
import parseISO from 'date-fns/parseISO';
|
5
|
+
import { InjectedFieldProps } from '../Field/InjectedFieldProps';
|
6
|
+
import Group, { GroupProps } from '../Group';
|
7
|
+
|
8
|
+
// Docs for react-date-picker https://www.npmjs.com/package/react-date-picker
|
9
|
+
|
10
|
+
// TODO: pick better home for this
|
11
|
+
export interface DateOnly {
|
12
|
+
year?: number;
|
13
|
+
month?: number;
|
14
|
+
day?: number;
|
15
|
+
}
|
16
|
+
|
17
|
+
type InjectedDate = InjectedFieldProps<DateOnly | undefined>;
|
18
|
+
|
19
|
+
export interface DatePickerInputProps
|
20
|
+
extends InjectedDate,
|
21
|
+
Omit<DatePickerProps, keyof InjectedDate | 'name' | 'value' | 'className'>,
|
22
|
+
Omit<GroupProps, keyof InjectedDate | 'children'> {}
|
23
|
+
|
24
|
+
export default function DatePickerInput({
|
25
|
+
input,
|
26
|
+
meta,
|
27
|
+
label,
|
28
|
+
helpText,
|
29
|
+
className,
|
30
|
+
disabled,
|
31
|
+
...rest
|
32
|
+
}: DatePickerInputProps) {
|
33
|
+
const [displayDate, setDisplayDate] = useState<Date | null>(null);
|
34
|
+
|
35
|
+
function handleChange(e: DatePickerProps['value'] | undefined) {
|
36
|
+
const { onChange } = input;
|
37
|
+
if (onChange == null) {
|
38
|
+
return;
|
39
|
+
}
|
40
|
+
|
41
|
+
if (!e) {
|
42
|
+
onChange(undefined);
|
43
|
+
setDisplayDate(null);
|
44
|
+
return;
|
45
|
+
}
|
46
|
+
|
47
|
+
if (e instanceof Date) {
|
48
|
+
const parsedValue = parseISO(e.toISOString().split('T')[0]);
|
49
|
+
|
50
|
+
setDisplayDate(parsedValue);
|
51
|
+
onChange({
|
52
|
+
year: e.getFullYear(),
|
53
|
+
month: e.getMonth() + 1,
|
54
|
+
day: e.getDate(),
|
55
|
+
});
|
56
|
+
} else {
|
57
|
+
// e is instanceof Date[]
|
58
|
+
const parsedValue = parseISO(e[0].toISOString().split('T')[0]);
|
59
|
+
|
60
|
+
setDisplayDate(parsedValue);
|
61
|
+
onChange({
|
62
|
+
year: e[0].getFullYear(),
|
63
|
+
month: e[0].getMonth() + 1,
|
64
|
+
day: e[0].getDate(),
|
65
|
+
});
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
return (
|
70
|
+
<Group
|
71
|
+
input={input}
|
72
|
+
meta={meta}
|
73
|
+
label={label}
|
74
|
+
helpText={helpText}
|
75
|
+
className={classnames(className, 'date-picker')}
|
76
|
+
disabled={disabled}>
|
77
|
+
<DatePicker
|
78
|
+
{...rest}
|
79
|
+
className={classnames('date-picker', className)}
|
80
|
+
value={displayDate}
|
81
|
+
onChange={handleChange}
|
82
|
+
/>
|
83
|
+
</Group>
|
84
|
+
);
|
85
|
+
}
|
@@ -0,0 +1,151 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`IconInputGroup has matching snapshot 1`] = `
|
4
|
+
<DocumentFragment>
|
5
|
+
<form
|
6
|
+
action="#"
|
7
|
+
>
|
8
|
+
<div
|
9
|
+
class="date-picker group"
|
10
|
+
>
|
11
|
+
<div
|
12
|
+
id="favoritedate-error-scroll-target"
|
13
|
+
style="display: none;"
|
14
|
+
/>
|
15
|
+
<label
|
16
|
+
for="favoriteDate"
|
17
|
+
>
|
18
|
+
Favorite Date
|
19
|
+
</label>
|
20
|
+
<div
|
21
|
+
class="react-date-picker react-date-picker--closed react-date-picker--enabled date-picker"
|
22
|
+
>
|
23
|
+
<div
|
24
|
+
class="react-date-picker__wrapper"
|
25
|
+
>
|
26
|
+
<div
|
27
|
+
class="react-date-picker__inputGroup"
|
28
|
+
>
|
29
|
+
<input
|
30
|
+
max="2023-09-23"
|
31
|
+
min="2022-06-22"
|
32
|
+
name="date"
|
33
|
+
style="visibility: hidden; position: absolute; z-index: -999;"
|
34
|
+
type="date"
|
35
|
+
value=""
|
36
|
+
/>
|
37
|
+
<input
|
38
|
+
autocomplete="off"
|
39
|
+
class="react-date-picker__inputGroup__input react-date-picker__inputGroup__month"
|
40
|
+
data-input="true"
|
41
|
+
inputmode="numeric"
|
42
|
+
max="12"
|
43
|
+
min="1"
|
44
|
+
name="month"
|
45
|
+
placeholder="mm"
|
46
|
+
type="number"
|
47
|
+
value=""
|
48
|
+
/>
|
49
|
+
<span
|
50
|
+
class="react-date-picker__inputGroup__divider"
|
51
|
+
>
|
52
|
+
/
|
53
|
+
</span>
|
54
|
+
<input
|
55
|
+
autocomplete="off"
|
56
|
+
class="react-date-picker__inputGroup__input react-date-picker__inputGroup__day"
|
57
|
+
data-input="true"
|
58
|
+
inputmode="numeric"
|
59
|
+
max="31"
|
60
|
+
min="1"
|
61
|
+
name="day"
|
62
|
+
placeholder="dd"
|
63
|
+
type="number"
|
64
|
+
value=""
|
65
|
+
/>
|
66
|
+
<span
|
67
|
+
class="react-date-picker__inputGroup__divider"
|
68
|
+
>
|
69
|
+
/
|
70
|
+
</span>
|
71
|
+
<input
|
72
|
+
autocomplete="off"
|
73
|
+
class="react-date-picker__inputGroup__input react-date-picker__inputGroup__year"
|
74
|
+
data-input="true"
|
75
|
+
inputmode="numeric"
|
76
|
+
max="2023"
|
77
|
+
min="2022"
|
78
|
+
name="year"
|
79
|
+
placeholder="yyyy"
|
80
|
+
step="1"
|
81
|
+
type="number"
|
82
|
+
value=""
|
83
|
+
/>
|
84
|
+
</div>
|
85
|
+
<button
|
86
|
+
class="react-date-picker__clear-button react-date-picker__button"
|
87
|
+
type="button"
|
88
|
+
>
|
89
|
+
<svg
|
90
|
+
class="react-date-picker__clear-button__icon react-date-picker__button__icon"
|
91
|
+
height="19"
|
92
|
+
stroke="black"
|
93
|
+
stroke-width="2"
|
94
|
+
viewBox="0 0 19 19"
|
95
|
+
width="19"
|
96
|
+
xmlns="http://www.w3.org/2000/svg"
|
97
|
+
>
|
98
|
+
<line
|
99
|
+
x1="4"
|
100
|
+
x2="15"
|
101
|
+
y1="4"
|
102
|
+
y2="15"
|
103
|
+
/>
|
104
|
+
<line
|
105
|
+
x1="15"
|
106
|
+
x2="4"
|
107
|
+
y1="4"
|
108
|
+
y2="15"
|
109
|
+
/>
|
110
|
+
</svg>
|
111
|
+
</button>
|
112
|
+
<button
|
113
|
+
class="react-date-picker__calendar-button react-date-picker__button"
|
114
|
+
type="button"
|
115
|
+
>
|
116
|
+
<svg
|
117
|
+
class="react-date-picker__calendar-button__icon react-date-picker__button__icon"
|
118
|
+
height="19"
|
119
|
+
stroke="black"
|
120
|
+
stroke-width="2"
|
121
|
+
viewBox="0 0 19 19"
|
122
|
+
width="19"
|
123
|
+
xmlns="http://www.w3.org/2000/svg"
|
124
|
+
>
|
125
|
+
<rect
|
126
|
+
fill="none"
|
127
|
+
height="15"
|
128
|
+
width="15"
|
129
|
+
x="2"
|
130
|
+
y="2"
|
131
|
+
/>
|
132
|
+
<line
|
133
|
+
x1="6"
|
134
|
+
x2="6"
|
135
|
+
y1="0"
|
136
|
+
y2="4"
|
137
|
+
/>
|
138
|
+
<line
|
139
|
+
x1="13"
|
140
|
+
x2="13"
|
141
|
+
y1="0"
|
142
|
+
y2="4"
|
143
|
+
/>
|
144
|
+
</svg>
|
145
|
+
</button>
|
146
|
+
</div>
|
147
|
+
</div>
|
148
|
+
</div>
|
149
|
+
</form>
|
150
|
+
</DocumentFragment>
|
151
|
+
`;
|
@@ -0,0 +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
|
+
}
|
@@ -0,0 +1,90 @@
|
|
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
|
+
|
8
|
+
// we attempted to support generic components but failed
|
9
|
+
// so, we assume the actual TRenderComponent has no generic arguments
|
10
|
+
// instead, any concrete TRenderComponent can utilize a TRenderComponent<TValue> as needed
|
11
|
+
|
12
|
+
type RenderComponent<TValue, TRenderComponent extends ElementType> = Partial<
|
13
|
+
ComponentProps<TRenderComponent>
|
14
|
+
> extends Partial<InjectedFieldProps<TValue>>
|
15
|
+
? TRenderComponent
|
16
|
+
: never;
|
17
|
+
|
18
|
+
type RenderComponentProps<
|
19
|
+
TValue,
|
20
|
+
TRenderComponent extends ElementType
|
21
|
+
> = Partial<ComponentProps<TRenderComponent>> extends Partial<
|
22
|
+
InjectedFieldProps<TValue>
|
23
|
+
>
|
24
|
+
? ComponentProps<TRenderComponent>
|
25
|
+
: never;
|
26
|
+
|
27
|
+
/** A specific Field instance to be rendered by the given TRenderComponent or by whatever default is reasonable */
|
28
|
+
export type FieldProps<
|
29
|
+
TForm extends object,
|
30
|
+
TProp extends keyof TForm,
|
31
|
+
TRenderComponent extends ElementType
|
32
|
+
> = {
|
33
|
+
name: TProp; // somewhat duplicated from useStandardFormInputProps but better for autocomplete
|
34
|
+
Component: RenderComponent<TForm[TProp], TRenderComponent>;
|
35
|
+
|
36
|
+
id?: string;
|
37
|
+
disabled?: boolean;
|
38
|
+
validate?:
|
39
|
+
| ValidationFunction<TForm[TProp]>
|
40
|
+
| ValidationFunction<TForm[TProp]>[];
|
41
|
+
normalize?: NormalizationFunction<TForm[TProp]>;
|
42
|
+
} & Omit<
|
43
|
+
RenderComponentProps<TForm[TProp], TRenderComponent>,
|
44
|
+
keyof InjectedFieldProps<TForm[TProp]>
|
45
|
+
>;
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Renders whatever Component is passed - injecting the formik values needed to finish wiring up that individual field.
|
49
|
+
* Should no Component be used then the default will be provided by the default lookup based on typeof(TForm[TProp])
|
50
|
+
*/
|
51
|
+
function Field<
|
52
|
+
TForm extends object,
|
53
|
+
TProp extends keyof TForm,
|
54
|
+
TRenderComponent extends ElementType
|
55
|
+
>(
|
56
|
+
{
|
57
|
+
name,
|
58
|
+
Component,
|
59
|
+
id,
|
60
|
+
normalize,
|
61
|
+
validate,
|
62
|
+
disabled,
|
63
|
+
...rest
|
64
|
+
}: FieldProps<TForm, TProp, TRenderComponent>,
|
65
|
+
ref: LegacyRef<any>
|
66
|
+
) {
|
67
|
+
const [input, meta] = useStandardFormInput<TForm[TProp]>({
|
68
|
+
name: String(name),
|
69
|
+
id: id,
|
70
|
+
normalize: normalize,
|
71
|
+
validate: validate,
|
72
|
+
disabled: disabled,
|
73
|
+
});
|
74
|
+
|
75
|
+
// a bit of a hack so JSX is happy with us
|
76
|
+
const Wrapped = Component as React.ComponentType<
|
77
|
+
InjectedFieldProps<TForm[TProp]>
|
78
|
+
>;
|
79
|
+
|
80
|
+
return (
|
81
|
+
<FieldNameContext.Provider value={input.name}>
|
82
|
+
<Wrapped {...rest} ref={ref} id={id} input={input} meta={meta} />
|
83
|
+
</FieldNameContext.Provider>
|
84
|
+
);
|
85
|
+
}
|
86
|
+
|
87
|
+
// hack to get forwarded refs to work
|
88
|
+
const FieldWithRef = React.forwardRef(Field as any);
|
89
|
+
|
90
|
+
export default FieldWithRef as typeof Field;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { useContext } from 'react';
|
2
|
+
import { FieldNameContext } from './FieldNameContext';
|
3
|
+
|
4
|
+
export default function FieldErrorScrollTarget() {
|
5
|
+
const name = useContext(FieldNameContext);
|
6
|
+
if (!name) {
|
7
|
+
return null;
|
8
|
+
}
|
9
|
+
const divId = `${name.toLowerCase()}-error-scroll-target`;
|
10
|
+
return <div id={divId} style={{ display: 'none' }} />;
|
11
|
+
}
|
@@ -0,0 +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
|
+
}
|
@@ -0,0 +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
|
+
}
|
@@ -0,0 +1,121 @@
|
|
1
|
+
import { useContext, useEffect } from 'react';
|
2
|
+
import { useField, useFormikContext } from 'formik';
|
3
|
+
import { CustomFieldInputProps } from './CustomFieldInputProps';
|
4
|
+
import { CustomFieldMetaProps } from './CustomFieldMetaProps';
|
5
|
+
import { FieldNameContext } from './FieldNameContext';
|
6
|
+
import { ServerErrorContext } from '../Form/ServerErrorContext';
|
7
|
+
import { NormalizationFunction } from '../Normalization/NormalizationFunction';
|
8
|
+
import { ValidationFunction } from '../Validation/ValidationFunction';
|
9
|
+
|
10
|
+
export interface useStandardFieldProps<TValue> {
|
11
|
+
id?: string;
|
12
|
+
name: string;
|
13
|
+
disabled?: boolean;
|
14
|
+
validate?: ValidationFunction<TValue> | ValidationFunction<TValue>[];
|
15
|
+
normalize?: NormalizationFunction<TValue>;
|
16
|
+
}
|
17
|
+
|
18
|
+
// provides a consistent way to deal with all form fields (non array)
|
19
|
+
export default function useStandardField<TValue>({
|
20
|
+
id: providedId,
|
21
|
+
name: providedName,
|
22
|
+
disabled,
|
23
|
+
validate,
|
24
|
+
normalize,
|
25
|
+
}: useStandardFieldProps<TValue>): [
|
26
|
+
CustomFieldInputProps<TValue>,
|
27
|
+
CustomFieldMetaProps<TValue>
|
28
|
+
] {
|
29
|
+
// because the formik errors are evaluated all at the same time we need to keep server errors separate
|
30
|
+
const { getError: getServerError, setError: setServerError } =
|
31
|
+
useContext(ServerErrorContext);
|
32
|
+
|
33
|
+
// ensure that form section values are obeyed, e.g. homeAddress.zipCode
|
34
|
+
const fieldNameContextValue = useContext(FieldNameContext);
|
35
|
+
const name = fieldNameContextValue
|
36
|
+
? `${fieldNameContextValue}.${providedName}`
|
37
|
+
: providedName;
|
38
|
+
|
39
|
+
// ensure that nested contexts don't have duplicate id issues when an id is specified
|
40
|
+
const id = providedId
|
41
|
+
? fieldNameContextValue
|
42
|
+
? `${fieldNameContextValue}.${providedId}`
|
43
|
+
: providedId
|
44
|
+
: name;
|
45
|
+
|
46
|
+
// ensure that our custom validation rules are handled
|
47
|
+
// e.g. we allow arrays of validators
|
48
|
+
const [formikInput, formikMeta] = useField<TValue>({
|
49
|
+
name,
|
50
|
+
id: id ? id : name,
|
51
|
+
disabled: disabled,
|
52
|
+
validate: callAllValidators,
|
53
|
+
});
|
54
|
+
const { setFieldValue, isSubmitting } = useFormikContext();
|
55
|
+
|
56
|
+
const touched =
|
57
|
+
formikMeta.touched !== false && formikMeta.touched !== undefined;
|
58
|
+
useEffect(() => {
|
59
|
+
if (!touched && isSubmitting) {
|
60
|
+
// because we do not always register all fields up front.
|
61
|
+
// e.g. formik expects even a 'create' form to have all fields given, at least, blank values
|
62
|
+
// that seems to be how it touches on submit:
|
63
|
+
// see: https://codesandbox.io/s/formik-example-4n7n8 vs https://codesandbox.io/s/formik-example-kttk5
|
64
|
+
// note in particular the change in line 24
|
65
|
+
// thus, we manually touch all fields here by calling onBlur
|
66
|
+
// there is a "setFieldTouched" from useFormikContext but it doesn't appear to work on field arrays
|
67
|
+
handleBlur();
|
68
|
+
}
|
69
|
+
});
|
70
|
+
|
71
|
+
// these are the props we expect consumers of this hook to pass directly to the input (or other control)
|
72
|
+
const resultInput: CustomFieldInputProps<TValue> = {
|
73
|
+
name: formikInput.name,
|
74
|
+
// pass any direct from server props through normalize without making the form dirty (e.g. phone number)
|
75
|
+
value: normalize ? normalize(formikInput.value) : formikInput.value,
|
76
|
+
onChange: handleChange,
|
77
|
+
onBlur: handleBlur,
|
78
|
+
// extensions to formik
|
79
|
+
id: id,
|
80
|
+
};
|
81
|
+
|
82
|
+
const resultMeta: CustomFieldMetaProps<TValue> = {
|
83
|
+
...formikMeta,
|
84
|
+
error: getServerError(name) || (touched ? formikMeta.error : undefined),
|
85
|
+
// extensions to formik
|
86
|
+
warning: undefined, // TODO - did this never work?
|
87
|
+
touched: touched,
|
88
|
+
};
|
89
|
+
|
90
|
+
return [resultInput, resultMeta];
|
91
|
+
|
92
|
+
function handleBlur() {
|
93
|
+
formikInput.onBlur({ target: { name: name } });
|
94
|
+
}
|
95
|
+
|
96
|
+
function handleChange(value: TValue) {
|
97
|
+
if (disabled) {
|
98
|
+
return;
|
99
|
+
}
|
100
|
+
const normalized = normalize ? normalize(value) : value;
|
101
|
+
setFieldValue(name, normalized);
|
102
|
+
setServerError(name, undefined);
|
103
|
+
}
|
104
|
+
|
105
|
+
function callAllValidators(value: TValue) {
|
106
|
+
if (disabled || !validate) {
|
107
|
+
return;
|
108
|
+
}
|
109
|
+
|
110
|
+
if (!Array.isArray(validate)) {
|
111
|
+
return validate(value);
|
112
|
+
}
|
113
|
+
|
114
|
+
for (let i = 0; i < validate.length; i++) {
|
115
|
+
const result = validate[i](value);
|
116
|
+
if (result) {
|
117
|
+
return result;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|