envoc-form 2.0.1-1 → 2.0.1-13

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 (155) hide show
  1. package/README.md +7 -7
  2. package/dist/css/envoc-form-styles.css +43 -5
  3. package/dist/css/envoc-form-styles.css.map +1 -1
  4. package/es/AddressInput/AddressInput.js +8 -7
  5. package/es/ConfirmBaseForm/ConfirmBaseForm.js +3 -2
  6. package/es/ConfirmDeleteForm/ConfirmDeleteForm.js +3 -2
  7. package/es/DatePickerInput/DatePickerInput.js +3 -2
  8. package/es/FileInput/DefaultFileList.js +36 -0
  9. package/es/FileInput/DropzoneFileInput.js +58 -0
  10. package/es/FileInput/FileInput.js +31 -9
  11. package/es/FileInput/index.js +2 -1
  12. package/es/Form/Form.js +11 -33
  13. package/es/Form/FormBasedPreventNavigation.js +1 -1
  14. package/es/FormGroupWrapper.js +2 -1
  15. package/es/FormInput/FormInput.js +29 -10
  16. package/es/FormInputArray/FormInputArray.js +39 -24
  17. package/es/IconInput.js +2 -1
  18. package/es/ReactSelectField/ReactSelectField.js +6 -3
  19. package/es/SubmitFormButton.js +2 -1
  20. package/es/__Tests__/FormTestBase.js +5 -2
  21. package/es/normalizers.js +10 -5
  22. package/es/useStandardFormInput.js +4 -2
  23. package/es/utils/index.js +3 -0
  24. package/es/utils/objectContainsNonSerializableProperty.js +16 -0
  25. package/es/utils/objectToFormData.js +65 -0
  26. package/es/utils/typeChecks.js +25 -0
  27. package/lib/AddressInput/AddressInput.js +15 -9
  28. package/lib/ConfirmBaseForm/ConfirmBaseForm.js +4 -2
  29. package/lib/ConfirmDeleteForm/ConfirmDeleteForm.js +6 -4
  30. package/lib/DatePickerInput/DatePickerInput.js +4 -2
  31. package/lib/FileInput/DefaultFileList.js +47 -0
  32. package/lib/FileInput/DropzoneFileInput.js +75 -0
  33. package/lib/FileInput/FileInput.js +39 -10
  34. package/lib/FileInput/index.js +13 -3
  35. package/lib/Form/Form.js +19 -39
  36. package/lib/Form/FormBasedPreventNavigation.js +7 -3
  37. package/lib/FormGroupWrapper.js +3 -1
  38. package/lib/FormInput/FormInput.js +31 -11
  39. package/lib/FormInputArray/FormInputArray.js +47 -26
  40. package/lib/FormSection.js +5 -1
  41. package/lib/IconInput.js +3 -1
  42. package/lib/ReactSelectField/ReactSelectField.js +13 -5
  43. package/lib/ReactSelectField/index.js +6 -2
  44. package/lib/SubmitFormButton.js +3 -1
  45. package/lib/__Tests__/FormTestBase.js +6 -2
  46. package/lib/index.js +7 -3
  47. package/lib/normalizers.js +10 -5
  48. package/lib/useStandardFormInput.js +5 -2
  49. package/lib/utils/index.js +23 -0
  50. package/lib/utils/objectContainsNonSerializableProperty.js +24 -0
  51. package/lib/utils/objectToFormData.js +73 -0
  52. package/lib/utils/typeChecks.js +58 -0
  53. package/lib/validators/index.js +5 -1
  54. package/package.json +99 -90
  55. package/src/AddressInput/AddesssInput.test.js +23 -23
  56. package/src/AddressInput/AddressInput.js +73 -73
  57. package/src/AddressInput/UsStates.js +53 -53
  58. package/src/AddressInput/__snapshots__/AddesssInput.test.js.snap +207 -207
  59. package/src/AddressInput/index.js +2 -2
  60. package/src/BoolInput/BoolInput.js +7 -7
  61. package/src/BoolInput/BoolInput.test.js +23 -23
  62. package/src/BoolInput/InlineBoolInput.js +7 -7
  63. package/src/BoolInput/__snapshots__/BoolInput.test.js.snap +89 -89
  64. package/src/BoolInput/boolOptions.js +6 -6
  65. package/src/BoolInput/index.js +4 -4
  66. package/src/ConfirmBaseForm/ConfirmBaseForm.js +37 -37
  67. package/src/ConfirmBaseForm/ConfirmBaseForm.test.js +14 -14
  68. package/src/ConfirmBaseForm/__snapshots__/ConfirmBaseForm.test.js.snap +23 -23
  69. package/src/ConfirmBaseForm/index.js +1 -1
  70. package/src/ConfirmDeleteForm/ConfirmDeleteForm.js +39 -39
  71. package/src/ConfirmDeleteForm/ConfirmDeleteForm.test.js +24 -24
  72. package/src/ConfirmDeleteForm/__snapshots__/ConfirmDeleteForm.test.js.snap +25 -25
  73. package/src/ConfirmDeleteForm/index.js +1 -1
  74. package/src/DatePickerInput/DatePickerInput.js +46 -46
  75. package/src/DatePickerInput/DatePickerInput.test.js +74 -74
  76. package/src/DatePickerInput/__snapshots__/DatePickerInput.test.js.snap +134 -131
  77. package/src/DatePickerInput/date-picker-input.scss +42 -42
  78. package/src/DatePickerInput/index.js +3 -3
  79. package/src/ErrorScrollTarget.js +6 -6
  80. package/src/FileInput/DefaultFileList.js +39 -0
  81. package/src/FileInput/DropzoneFileInput.js +56 -0
  82. package/src/FileInput/DropzoneFileInput.test.js +24 -0
  83. package/src/FileInput/FileInput.js +77 -49
  84. package/src/FileInput/FileInput.test.js +24 -15
  85. package/src/FileInput/__snapshots__/DropzoneFileInput.test.js.snap +57 -0
  86. package/src/FileInput/__snapshots__/FileInput.test.js.snap +58 -22
  87. package/src/FileInput/file-input.scss +58 -17
  88. package/src/FileInput/index.js +4 -3
  89. package/src/Form/FocusError.js +48 -48
  90. package/src/Form/Form.js +139 -161
  91. package/src/Form/Form.test.js +23 -23
  92. package/src/Form/FormBasedPreventNavigation.js +25 -25
  93. package/src/Form/ServerErrorContext.js +7 -7
  94. package/src/Form/__snapshots__/Form.test.js.snap +9 -9
  95. package/src/Form/index.js +3 -3
  96. package/src/FormGroup.js +30 -30
  97. package/src/FormGroupWrapper.js +28 -28
  98. package/src/FormInput/FormInput.js +144 -136
  99. package/src/FormInput/FormInput.test.js +66 -66
  100. package/src/FormInput/__snapshots__/FormInput.test.js.snap +323 -313
  101. package/src/FormInput/form-input.scss +9 -9
  102. package/src/FormInput/index.js +2 -2
  103. package/src/FormInputArray/FormInputArray.js +224 -210
  104. package/src/FormInputArray/FormInputArray.test.js +108 -59
  105. package/src/FormInputArray/__snapshots__/FormInputArray.test.js.snap +52 -40
  106. package/src/FormInputArray/form-input-array.scss +13 -8
  107. package/src/FormInputArray/index.js +2 -2
  108. package/src/FormSection.js +13 -13
  109. package/src/IconInput.js +31 -31
  110. package/src/InlineFormInput/InlineFormInput.js +6 -6
  111. package/src/InlineFormInput/InlineFormInput.test.js +23 -23
  112. package/src/InlineFormInput/__snapshots__/InlineFormInput.test.js.snap +26 -26
  113. package/src/InlineFormInput/index.js +3 -3
  114. package/src/InlineFormInput/inline-form-input.scss +3 -3
  115. package/src/MoneyInput/InlineMoneyInput.js +7 -7
  116. package/src/MoneyInput/MoneyInput.js +7 -7
  117. package/src/MoneyInput/MoneyInputs.test.js +43 -43
  118. package/src/MoneyInput/__snapshots__/MoneyInputs.test.js.snap +81 -81
  119. package/src/MoneyInput/index.js +4 -4
  120. package/src/MoneyInput/money-input.scss +3 -3
  121. package/src/MoneyInput/moneyInputProps.js +12 -12
  122. package/src/NestedFormFieldContext.js +6 -6
  123. package/src/ReactSelectField/ReactSelectField.js +122 -120
  124. package/src/ReactSelectField/index.js +6 -6
  125. package/src/ReactSelectField/react-select-field.scss +5 -5
  126. package/src/StandardFormActions.js +27 -27
  127. package/src/SubmitFormButton.js +28 -28
  128. package/src/__Tests__/FormTestBase.js +14 -11
  129. package/src/__Tests__/IconInput.test.js +23 -23
  130. package/src/__Tests__/StandardFormActions.test.js +23 -23
  131. package/src/__Tests__/SubmitFormButton.test.js +23 -23
  132. package/src/__Tests__/__snapshots__/IconInput.test.js.snap +38 -38
  133. package/src/__Tests__/__snapshots__/StandardFormActions.test.js.snap +25 -25
  134. package/src/__Tests__/__snapshots__/SubmitFormButton.test.js.snap +18 -18
  135. package/src/__Tests__/index.js +2 -2
  136. package/src/_variables.scss +11 -11
  137. package/src/index.js +33 -33
  138. package/src/normalizers.js +42 -32
  139. package/src/selectors.js +3 -3
  140. package/src/styles.scss +7 -7
  141. package/src/useStandardFormInput.js +118 -118
  142. package/src/utils/index.js +3 -0
  143. package/src/utils/objectContainsNonSerializableProperty.js +15 -0
  144. package/src/utils/objectContainsNonSerializableProperty.test.js +49 -0
  145. package/src/utils/objectToFormData.js +89 -0
  146. package/src/utils/objectToFormData.test.js +76 -0
  147. package/src/utils/typeChecks.js +18 -0
  148. package/src/validators/index.js +2 -2
  149. package/src/validators/validators.js +93 -93
  150. package/src/validators/validators.test.js +79 -79
  151. package/CHANGELOG.json +0 -95
  152. package/CHANGELOG.md +0 -58
  153. package/es/FormInput/utilities.js +0 -71
  154. package/lib/FormInput/utilities.js +0 -86
  155. package/src/FormInput/utilities.js +0 -26
@@ -1,136 +1,144 @@
1
- import React from 'react';
2
- import classnames from 'classnames';
3
- import {
4
- Input as BootstrapInput,
5
- FormFeedback,
6
- CustomInput,
7
- FormText,
8
- Alert,
9
- } from 'reactstrap';
10
- import lru from 'lru-cache';
11
- import PropTypes from 'prop-types';
12
- import TextareaAutosize from 'react-textarea-autosize';
13
- import { useAxiosRequest } from 'envoc-request';
14
- import FormGroupWrapper from '../FormGroupWrapper';
15
- import DatePickerInput from '../DatePickerInput';
16
- import ReactSelectField from '../ReactSelectField';
17
- import useStandardFormInput from '../useStandardFormInput';
18
- import FileInput from '../FileInput';
19
-
20
- export default function FormInput(props) {
21
- const [input, meta] = useStandardFormInput(props);
22
- const { className, hide } = props;
23
- return (
24
- <StandardFieldGroup
25
- {...input}
26
- className={classnames({ 'd-none': hide }, className)}
27
- meta={meta}
28
- />
29
- );
30
- }
31
-
32
- FormInput.propTypes = {
33
- id: PropTypes.string,
34
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
35
- name: PropTypes.string.isRequired,
36
- placeholder: PropTypes.string,
37
- helpText: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
38
- };
39
-
40
- function StandardFieldGroup(props) {
41
- switch (props.type) {
42
- case 'date':
43
- return <FormGroupWrapper {...props} Component={DatePicker} />;
44
- case 'select':
45
- if (props.optionsUrl) {
46
- return <FormGroupWrapper {...props} Component={RemoteSelect} />;
47
- } else {
48
- return <FormGroupWrapper {...props} Component={Select} />;
49
- }
50
- case 'checkbox':
51
- case 'radio':
52
- return Checkbox(props);
53
- case 'file':
54
- return <FormGroupWrapper {...props} Component={FileInput} />;
55
- case 'textarea':
56
- return <FormGroupWrapper {...props} Component={TextAreaInput} />;
57
- default:
58
- return <FormGroupWrapper {...props} Component={DefaultInput} />;
59
- }
60
- }
61
-
62
- const TextAreaInput = ({ className, meta, helpText, ...props }) => {
63
- return (
64
- <TextareaAutosize
65
- cacheMeasurements
66
- className={classnames(
67
- className,
68
- 'form-control',
69
- meta.error ? 'is-invalid' : ''
70
- )}
71
- {...props}
72
- />
73
- );
74
- };
75
-
76
- const DefaultInput = ({ meta, ...props }) => {
77
- return <BootstrapInput invalid={!!meta.error} {...props} />;
78
- };
79
-
80
- const Select = ({ includeEmptyOption = true, options, ...props }) => {
81
- const allOptions = includeEmptyOption
82
- ? [{ label: ' ', value: null }, ...options]
83
- : options;
84
- return <ReactSelectField {...props} options={allOptions} />;
85
- };
86
-
87
- export const optionCache = new lru({ max: 500, maxAge: 1000 * 60 * 5 });
88
- const RemoteSelect = ({
89
- optionsUrl,
90
- includeEmptyOption = true,
91
- includeOtherOption = false,
92
- ...props
93
- }) => {
94
- const request = {
95
- method: 'get',
96
- url: optionsUrl,
97
- cache: optionCache,
98
- autoExecute: true,
99
- };
100
- const webRequest = useAxiosRequest(request);
101
- if (webRequest.error) {
102
- return <Alert color="danger">An error occurred while loading.</Alert>;
103
- }
104
-
105
- const options = [];
106
-
107
- if (webRequest.loading) {
108
- options.push({ label: 'Loading...', value: '' });
109
- } else {
110
- if (includeEmptyOption) {
111
- options.push({ label: ' ', value: null });
112
- }
113
- options.push(...webRequest.resp.data.result);
114
- if (includeOtherOption) {
115
- options.push({ label: 'Other', value: 'other' });
116
- }
117
- }
118
-
119
- return <ReactSelectField {...props} options={options} />;
120
- };
121
-
122
- const DatePicker = ({ meta, ...props }) => {
123
- return (
124
- <DatePickerInput {...props} className={meta.error ? 'is-invalid' : ''} />
125
- );
126
- };
127
-
128
- const Checkbox = ({ helpText, meta, ...props }) => {
129
- return (
130
- <React.Fragment>
131
- <CustomInput {...props} />
132
- {meta.error && <FormFeedback>{meta.error}</FormFeedback>}
133
- {helpText && <FormText>{helpText}</FormText>}
134
- </React.Fragment>
135
- );
136
- };
1
+ import React from 'react';
2
+ import classnames from 'classnames';
3
+ import {
4
+ Input as BootstrapInput,
5
+ FormFeedback,
6
+ CustomInput,
7
+ FormText,
8
+ Alert,
9
+ } from 'reactstrap';
10
+ import lru from 'lru-cache';
11
+ import PropTypes from 'prop-types';
12
+ import TextareaAutosize from 'react-textarea-autosize';
13
+ import { useAxiosRequest } from 'envoc-request';
14
+ import FormGroupWrapper from '../FormGroupWrapper';
15
+ import DatePickerInput from '../DatePickerInput';
16
+ import ReactSelectField from '../ReactSelectField';
17
+ import useStandardFormInput from '../useStandardFormInput';
18
+ import { FileInput, DropzoneFileInput } from '../FileInput';
19
+
20
+ export default function FormInput(props) {
21
+ const [input, meta] = useStandardFormInput(props);
22
+ const { className, hide } = props;
23
+ return (
24
+ <StandardFieldGroup
25
+ {...input}
26
+ className={classnames({ 'd-none': hide }, className)}
27
+ meta={meta}
28
+ />
29
+ );
30
+ }
31
+
32
+ FormInput.propTypes = {
33
+ id: PropTypes.string,
34
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
35
+ name: PropTypes.string.isRequired,
36
+ placeholder: PropTypes.string,
37
+ helpText: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
38
+ };
39
+
40
+ function StandardFieldGroup(props) {
41
+ switch (props.type) {
42
+ case 'date':
43
+ return <FormGroupWrapper {...props} Component={DatePicker} />;
44
+ case 'select':
45
+ if (props.optionsUrl) {
46
+ return <FormGroupWrapper {...props} Component={RemoteSelect} />;
47
+ } else {
48
+ return <FormGroupWrapper {...props} Component={Select} />;
49
+ }
50
+ case 'checkbox':
51
+ case 'radio':
52
+ return Checkbox(props);
53
+ case 'file':
54
+ if (props.dropzone) {
55
+ return <FormGroupWrapper {...props} Component={DropzoneFileInput} />;
56
+ }
57
+ return <FormGroupWrapper {...props} Component={FileInput} />;
58
+ case 'textarea':
59
+ return <FormGroupWrapper {...props} Component={TextAreaInput} />;
60
+ default:
61
+ return <FormGroupWrapper {...props} Component={DefaultInput} />;
62
+ }
63
+ }
64
+
65
+ const TextAreaInput = ({ className, meta, helpText, ...props }) => {
66
+ return (
67
+ <TextareaAutosize
68
+ cacheMeasurements
69
+ className={classnames(
70
+ className,
71
+ 'form-control',
72
+ meta.error ? 'is-invalid' : ''
73
+ )}
74
+ {...props}
75
+ />
76
+ );
77
+ };
78
+
79
+ const DefaultInput = ({ meta, ...props }) => {
80
+ return <BootstrapInput invalid={!!meta.error} {...props} />;
81
+ };
82
+
83
+ const Select = ({ includeEmptyOption = true, options, ...props }) => {
84
+ const allOptions = includeEmptyOption
85
+ ? [{ label: ' ', value: null }, ...options]
86
+ : options;
87
+ return <ReactSelectField {...props} options={allOptions} />;
88
+ };
89
+
90
+ // low cache value just to prevent the same dropdown from hitting the API at the same time
91
+ // TODO: global cache provider / "envoc-cache" instead of this static instance
92
+ export const optionCache = new lru({ max: 500, maxAge: 1000 * 10 });
93
+ const RemoteSelect = ({
94
+ optionsUrl,
95
+ includeEmptyOption = true,
96
+ includeOtherOption = false,
97
+ cache = optionCache,
98
+ maxAge = 1000 * 10,
99
+ ...props
100
+ }) => {
101
+ const request = {
102
+ method: 'get',
103
+ url: optionsUrl,
104
+ cache: cache,
105
+ maxAge: maxAge,
106
+ autoExecute: true,
107
+ };
108
+ const webRequest = useAxiosRequest(request);
109
+ if (webRequest.error) {
110
+ return <Alert color="danger">An error occurred while loading.</Alert>;
111
+ }
112
+
113
+ const options = [];
114
+
115
+ if (webRequest.loading) {
116
+ options.push({ label: 'Loading...', value: '' });
117
+ } else {
118
+ if (includeEmptyOption) {
119
+ options.push({ label: ' ', value: null });
120
+ }
121
+ options.push(...webRequest.resp.data.result);
122
+ if (includeOtherOption) {
123
+ options.push({ label: 'Other', value: 'other' });
124
+ }
125
+ }
126
+
127
+ return <ReactSelectField {...props} options={options} />;
128
+ };
129
+
130
+ const DatePicker = ({ meta, ...props }) => {
131
+ return (
132
+ <DatePickerInput {...props} className={meta.error ? 'is-invalid' : ''} />
133
+ );
134
+ };
135
+
136
+ const Checkbox = ({ helpText, meta, ...props }) => {
137
+ return (
138
+ <React.Fragment>
139
+ <CustomInput {...props} />
140
+ {meta.error && <FormFeedback>{meta.error}</FormFeedback>}
141
+ {helpText && <FormText>{helpText}</FormText>}
142
+ </React.Fragment>
143
+ );
144
+ };
@@ -1,66 +1,66 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import '@testing-library/jest-dom/extend-expect';
4
- import { FormTestBase } from '../__Tests__';
5
- import FormInput from './FormInput';
6
- HTMLCanvasElement.prototype.getContext = () => {};
7
-
8
- describe('FormInput', () => {
9
- it('renders without crashing', () => {
10
- render(
11
- <FormTestBase>
12
- <FormInput name="test" />
13
- </FormTestBase>
14
- );
15
- });
16
-
17
- it('has matching datepicker snapshot', () => {
18
- const renderResult = render(
19
- <FormTestBase>
20
- <FormInput
21
- name="test"
22
- minDate={new Date('9/23/2020')}
23
- maxDate={new Date('09/23/2021')}
24
- type="date"
25
- />
26
- </FormTestBase>
27
- );
28
- expect(renderResult.asFragment()).toMatchSnapshot();
29
- });
30
-
31
- it('has matching textarea snapshot', () => {
32
- const renderResult = render(
33
- <FormTestBase>
34
- <FormInput name="test" type="textarea" />
35
- </FormTestBase>
36
- );
37
- expect(renderResult.asFragment()).toMatchSnapshot();
38
- });
39
-
40
- it('has matching checkbox snapshot', () => {
41
- const renderResult = render(
42
- <FormTestBase>
43
- <FormInput name="test" type="checkbox" />
44
- </FormTestBase>
45
- );
46
- expect(renderResult.asFragment()).toMatchSnapshot();
47
- });
48
-
49
- it('has matching file input snapshot', () => {
50
- const renderResult = render(
51
- <FormTestBase>
52
- <FormInput name="test" type="file" />
53
- </FormTestBase>
54
- );
55
- expect(renderResult.asFragment()).toMatchSnapshot();
56
- });
57
-
58
- it('has matching select snapshot', () => {
59
- const renderResult = render(
60
- <FormTestBase>
61
- <FormInput name="test" type="select" options={[]} />
62
- </FormTestBase>
63
- );
64
- expect(renderResult.asFragment()).toMatchSnapshot();
65
- });
66
- });
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/extend-expect';
4
+ import { FormTestBase } from '../__Tests__';
5
+ import FormInput from './FormInput';
6
+ HTMLCanvasElement.prototype.getContext = () => {};
7
+
8
+ describe('FormInput', () => {
9
+ it('renders without crashing', () => {
10
+ render(
11
+ <FormTestBase>
12
+ <FormInput name="test" />
13
+ </FormTestBase>
14
+ );
15
+ });
16
+
17
+ it('has matching datepicker snapshot', () => {
18
+ const renderResult = render(
19
+ <FormTestBase>
20
+ <FormInput
21
+ name="test"
22
+ minDate={new Date('9/23/2020')}
23
+ maxDate={new Date('09/23/2021')}
24
+ type="date"
25
+ />
26
+ </FormTestBase>
27
+ );
28
+ expect(renderResult.asFragment()).toMatchSnapshot();
29
+ });
30
+
31
+ it('has matching textarea snapshot', () => {
32
+ const renderResult = render(
33
+ <FormTestBase>
34
+ <FormInput name="test" type="textarea" />
35
+ </FormTestBase>
36
+ );
37
+ expect(renderResult.asFragment()).toMatchSnapshot();
38
+ });
39
+
40
+ it('has matching checkbox snapshot', () => {
41
+ const renderResult = render(
42
+ <FormTestBase>
43
+ <FormInput name="test" type="checkbox" />
44
+ </FormTestBase>
45
+ );
46
+ expect(renderResult.asFragment()).toMatchSnapshot();
47
+ });
48
+
49
+ it('has matching file input snapshot', () => {
50
+ const renderResult = render(
51
+ <FormTestBase>
52
+ <FormInput name="test" type="file" />
53
+ </FormTestBase>
54
+ );
55
+ expect(renderResult.asFragment()).toMatchSnapshot();
56
+ });
57
+
58
+ it('has matching select snapshot', () => {
59
+ const renderResult = render(
60
+ <FormTestBase>
61
+ <FormInput name="test" type="select" options={[]} />
62
+ </FormTestBase>
63
+ );
64
+ expect(renderResult.asFragment()).toMatchSnapshot();
65
+ });
66
+ });