envoc-form 3.2.0 → 3.3.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.
@@ -1,2 +1,3 @@
1
1
  import AddressInput from './AddressInput';
2
- export default AddressInput;
2
+ import UsStates from './UsStates';
3
+ export { AddressInput as default, UsStates };
@@ -14,7 +14,7 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
14
14
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
15
15
 
16
16
  import React from 'react';
17
- import DatePicker from 'react-date-picker';
17
+ import DatePicker from 'react-date-picker/dist/entry.nostyle';
18
18
  import parseISO from 'date-fns/parseISO';
19
19
  import classnames from 'classnames';
20
20
  var dateOnlyRegex = /^\d{4}-\d{2}-\d{2}$/;
@@ -1,3 +1,4 @@
1
1
  import FileInput from './FileInput';
2
2
  import DropzoneFileInput from './DropzoneFileInput';
3
- export { FileInput, DropzoneFileInput };
3
+ import DefaultFileList from './DefaultFileList';
4
+ export { FileInput, DropzoneFileInput, DefaultFileList };
package/es/Form/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import FocusError from './FocusError';
1
2
  import Form from './Form';
3
+ import FormBasedPreventNavigation from './FormBasedPreventNavigation';
2
4
  import ServerErrorContext from './ServerErrorContext';
3
- export { Form as default, ServerErrorContext };
5
+ export { Form as default, ServerErrorContext, FocusError, FormBasedPreventNavigation };
@@ -19,6 +19,7 @@ import FormGroupWrapper from '../FormGroupWrapper';
19
19
  import DatePickerInput from '../DatePickerInput';
20
20
  import ReactSelectField from '../ReactSelectField';
21
21
  import useStandardFormInput from '../useStandardFormInput';
22
+ import { MoneyFormattedInput } from '../MoneyFormattedInput';
22
23
  import { FileInput, DropzoneFileInput } from '../FileInput';
23
24
  export default function FormInput(props) {
24
25
  var _useStandardFormInput = useStandardFormInput(props),
@@ -81,6 +82,11 @@ function StandardFieldGroup(props) {
81
82
  Component: TextAreaInput
82
83
  }));
83
84
 
85
+ case 'moneyFormatted':
86
+ return /*#__PURE__*/React.createElement(FormGroupWrapper, _extends({}, props, {
87
+ Component: MoneyFormattedInput
88
+ }));
89
+
84
90
  default:
85
91
  return /*#__PURE__*/React.createElement(FormGroupWrapper, _extends({}, props, {
86
92
  Component: DefaultInput
@@ -0,0 +1,106 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import React, { useEffect, useMemo, useState } from 'react';
3
+ import { useField } from 'formik';
4
+ import debounce from 'lodash/debounce';
5
+ import classNames from 'classnames'; // Money input that will format the value to always have commas, a single decimal, and
6
+ // exactly two digits after the decimal. This happens after a delay (using debounce).
7
+
8
+ export default function MoneyFormattedInput(_ref) {
9
+ var name = _ref.name,
10
+ onBlur = _ref.onBlur,
11
+ onChange = _ref.onChange,
12
+ classname = _ref.classname,
13
+ _ref$disabled = _ref.disabled,
14
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
15
+ _ref$debounceTimer = _ref.debounceTimer,
16
+ debounceTimer = _ref$debounceTimer === void 0 ? 1500 : _ref$debounceTimer,
17
+ meta = _ref.meta;
18
+
19
+ // The displayed state and formik state are two seperate values that we handle
20
+ var _useState = useState(''),
21
+ _useState2 = _slicedToArray(_useState, 2),
22
+ inputValue = _useState2[0],
23
+ setInputValue = _useState2[1];
24
+
25
+ var _useField = useField(name),
26
+ _useField2 = _slicedToArray(_useField, 1),
27
+ formikValue = _useField2[0].value;
28
+
29
+ var handleChangeDebounce = useMemo(function () {
30
+ return debounce(debouncedUpdateInput, debounceTimer);
31
+
32
+ function debouncedUpdateInput(value) {
33
+ var result = formatToCurrency(value);
34
+ setInputValue(result !== null && result !== void 0 ? result : ''); // sets value in formik
35
+
36
+ onChange(result !== null && result !== void 0 ? result : '');
37
+ onBlur();
38
+ }
39
+ }, [onBlur, onChange]); // Format first render
40
+
41
+ useEffect(function () {
42
+ var formattedFormikValue = formatToCurrency(formikValue);
43
+ setInputValue(formattedFormikValue !== null && formattedFormikValue !== void 0 ? formattedFormikValue : '');
44
+ }, [formikValue]);
45
+
46
+ function handleChange(e) {
47
+ var onlyNumbersDecimalComma = e.target.value.toString().replace(/[^.,0-9]/g, '');
48
+ setInputValue(onlyNumbersDecimalComma);
49
+ handleChangeDebounce(onlyNumbersDecimalComma);
50
+ }
51
+
52
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
53
+ className: "input-group"
54
+ }, /*#__PURE__*/React.createElement("div", {
55
+ className: "input-group-prepend"
56
+ }, /*#__PURE__*/React.createElement("span", {
57
+ className: "input-group-text"
58
+ }, "$")), /*#__PURE__*/React.createElement("input", {
59
+ name: name,
60
+ type: "text",
61
+ value: inputValue,
62
+ onChange: handleChange,
63
+ onBlur: onBlur,
64
+ disabled: disabled,
65
+ className: classNames(classname, meta.error === 'Required' ? 'is-invalid' : '', 'react-select-input money-input form-control')
66
+ })));
67
+ }
68
+
69
+ function formatToCurrency(value) {
70
+ if (value === null || value === undefined) {
71
+ return null;
72
+ } // 'value' is sometimes a number on first render
73
+
74
+
75
+ var onlyNumbersDecimal = value.toString().replace(/[^.0-9]/g, '');
76
+
77
+ if (!onlyNumbersDecimal) {
78
+ return null;
79
+ }
80
+
81
+ var result = new Intl.NumberFormat('en-US', {
82
+ style: 'decimal',
83
+ minimumSignificantDigits: 2,
84
+ minimumFractionDigits: 2
85
+ }).format(parseFloat(onlyNumbersDecimal));
86
+ result = formatTwoDecimalPlaces(result);
87
+ return result;
88
+ }
89
+
90
+ function formatTwoDecimalPlaces(value) {
91
+ var decimalIndex = value.indexOf('.'); // If the string doesn't contain a decimal OR
92
+ // the string contains a single '.' with nothing to the right of the decimal -> append '.00'
93
+ // Reason: parseFloat will remove '.00' from whole numbers (ex. 350.00 -> 350)
94
+
95
+ if (!value.includes('.')) {
96
+ return value.concat('.00');
97
+ } // If 2 or more characters to the right of the decimal
98
+ else if (!!value.charAt(decimalIndex + 2)) {
99
+ return value.substring(0, decimalIndex + 3);
100
+ } // If only 1 character to the right of the decimal
101
+ else if (!!value.charAt(decimalIndex + 1)) {
102
+ return value.substring(0, decimalIndex + 2).concat('0');
103
+ }
104
+
105
+ return value;
106
+ }
@@ -0,0 +1,2 @@
1
+ import MoneyFormattedInput from './MoneyFormattedInput';
2
+ export { MoneyFormattedInput };
package/es/index.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import * as normalizers from './normalizers';
2
2
  import { BoolInput, InlineBoolInput } from './BoolInput';
3
3
  import { InlineMoneyInput, MoneyInput } from './MoneyInput';
4
- import AddressInput from './AddressInput';
4
+ import { MoneyFormattedInput } from './MoneyFormattedInput';
5
+ import AddressInput, { UsStates } from './AddressInput';
5
6
  import ConfirmBaseForm from './ConfirmBaseForm';
6
7
  import ConfirmDeleteForm from './ConfirmDeleteForm';
8
+ import DatePickerInput from './DatePickerInput';
7
9
  import ErrorScrollTarget from './ErrorScrollTarget';
8
- import Form from './Form';
10
+ import { FileInput, DropzoneFileInput, DefaultFileList } from './FileInput';
11
+ import Form, { ServerErrorContext, FocusError, FormBasedPreventNavigation } from './Form';
9
12
  import FormGroup from './FormGroup';
10
13
  import FormGroupWrapper from './FormGroupWrapper';
11
14
  import FormInput from './FormInput';
@@ -17,4 +20,6 @@ import StandardFormActions from './StandardFormActions';
17
20
  import SubmitFormButton from './SubmitFormButton';
18
21
  import useStandardFormInput from './useStandardFormInput';
19
22
  import validators from './validators';
20
- export { AddressInput, BoolInput, ConfirmBaseForm, ConfirmDeleteForm, ErrorScrollTarget, Form, FormGroup, FormGroupWrapper, FormInput, FormInputArray, FormSection, IconInput, InlineBoolInput, InlineFormInput, InlineMoneyInput, MoneyInput, normalizers, StandardFormActions, SubmitFormButton, useStandardFormInput, validators };
23
+ import ReactSelectField, { customStyles as customReactSelectFieldStyles, overrideTheme as overrideReactSelectFieldStyles } from './ReactSelectField';
24
+ import NestedFormFieldContext from './NestedFormFieldContext';
25
+ export { AddressInput, UsStates, BoolInput, ConfirmBaseForm, ConfirmDeleteForm, DatePickerInput, ErrorScrollTarget, FileInput, DropzoneFileInput, DefaultFileList, Form, FormGroup, FormGroupWrapper, FormInput, FormInputArray, FormSection, IconInput, InlineBoolInput, InlineFormInput, InlineMoneyInput, MoneyInput, MoneyFormattedInput, normalizers, StandardFormActions, SubmitFormButton, useStandardFormInput, validators, ServerErrorContext, FocusError, FormBasedPreventNavigation, ReactSelectField, customReactSelectFieldStyles, overrideReactSelectFieldStyles, NestedFormFieldContext };
@@ -57,7 +57,7 @@ export function minCount(count) {
57
57
  }
58
58
  export var maxValue = function maxValue(value) {
59
59
  return function (inputValue) {
60
- if (inputValue && value) {
60
+ if (inputValue != null && value != null) {
61
61
  return inputValue <= value ? undefined : "Maximum value ".concat(value, " exceeded");
62
62
  } else {
63
63
  return undefined;
@@ -66,7 +66,7 @@ export var maxValue = function maxValue(value) {
66
66
  };
67
67
  export var minValue = function minValue(value) {
68
68
  return function (inputValue) {
69
- if (inputValue && value) {
69
+ if (inputValue != null && value != null) {
70
70
  return inputValue >= value ? undefined : "Minimum value ".concat(value, " not met");
71
71
  } else {
72
72
  return undefined;
@@ -5,9 +5,19 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports["default"] = void 0;
8
+ Object.defineProperty(exports, "default", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _AddressInput["default"];
12
+ }
13
+ });
14
+ Object.defineProperty(exports, "UsStates", {
15
+ enumerable: true,
16
+ get: function get() {
17
+ return _UsStates["default"];
18
+ }
19
+ });
9
20
 
10
21
  var _AddressInput = _interopRequireDefault(require("./AddressInput"));
11
22
 
12
- var _default = _AddressInput["default"];
13
- exports["default"] = _default;
23
+ var _UsStates = _interopRequireDefault(require("./UsStates"));
@@ -27,7 +27,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
27
27
 
28
28
  var _react = _interopRequireDefault(require("react"));
29
29
 
30
- var _reactDatePicker = _interopRequireDefault(require("react-date-picker"));
30
+ var _entry = _interopRequireDefault(require("react-date-picker/dist/entry.nostyle"));
31
31
 
32
32
  var _parseISO = _interopRequireDefault(require("date-fns/parseISO"));
33
33
 
@@ -96,7 +96,7 @@ var DatePickerInput = /*#__PURE__*/function (_React$Component) {
96
96
  }
97
97
 
98
98
  var parsedValue = value ? (0, _parseISO["default"])(value) : null;
99
- return /*#__PURE__*/_react["default"].createElement(_reactDatePicker["default"], (0, _extends2["default"])({
99
+ return /*#__PURE__*/_react["default"].createElement(_entry["default"], (0, _extends2["default"])({
100
100
  className: (0, _classnames["default"])('form-control', className),
101
101
  onCalendarOpen: this.onCalendarOpen
102
102
  }, rest, {
@@ -17,7 +17,15 @@ Object.defineProperty(exports, "DropzoneFileInput", {
17
17
  return _DropzoneFileInput["default"];
18
18
  }
19
19
  });
20
+ Object.defineProperty(exports, "DefaultFileList", {
21
+ enumerable: true,
22
+ get: function get() {
23
+ return _DefaultFileList["default"];
24
+ }
25
+ });
20
26
 
21
27
  var _FileInput = _interopRequireDefault(require("./FileInput"));
22
28
 
23
- var _DropzoneFileInput = _interopRequireDefault(require("./DropzoneFileInput"));
29
+ var _DropzoneFileInput = _interopRequireDefault(require("./DropzoneFileInput"));
30
+
31
+ var _DefaultFileList = _interopRequireDefault(require("./DefaultFileList"));
package/lib/Form/index.js CHANGED
@@ -5,12 +5,24 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
+ Object.defineProperty(exports, "FocusError", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _FocusError["default"];
12
+ }
13
+ });
8
14
  Object.defineProperty(exports, "default", {
9
15
  enumerable: true,
10
16
  get: function get() {
11
17
  return _Form["default"];
12
18
  }
13
19
  });
20
+ Object.defineProperty(exports, "FormBasedPreventNavigation", {
21
+ enumerable: true,
22
+ get: function get() {
23
+ return _FormBasedPreventNavigation["default"];
24
+ }
25
+ });
14
26
  Object.defineProperty(exports, "ServerErrorContext", {
15
27
  enumerable: true,
16
28
  get: function get() {
@@ -18,6 +30,10 @@ Object.defineProperty(exports, "ServerErrorContext", {
18
30
  }
19
31
  });
20
32
 
33
+ var _FocusError = _interopRequireDefault(require("./FocusError"));
34
+
21
35
  var _Form = _interopRequireDefault(require("./Form"));
22
36
 
37
+ var _FormBasedPreventNavigation = _interopRequireDefault(require("./FormBasedPreventNavigation"));
38
+
23
39
  var _ServerErrorContext = _interopRequireDefault(require("./ServerErrorContext"));
@@ -38,6 +38,8 @@ var _ReactSelectField = _interopRequireDefault(require("../ReactSelectField"));
38
38
 
39
39
  var _useStandardFormInput3 = _interopRequireDefault(require("../useStandardFormInput"));
40
40
 
41
+ var _MoneyFormattedInput = require("../MoneyFormattedInput");
42
+
41
43
  var _FileInput = require("../FileInput");
42
44
 
43
45
  var _excluded = ["className", "meta", "helpText"],
@@ -109,6 +111,11 @@ function StandardFieldGroup(props) {
109
111
  Component: TextAreaInput
110
112
  }));
111
113
 
114
+ case 'moneyFormatted':
115
+ return /*#__PURE__*/_react["default"].createElement(_FormGroupWrapper["default"], (0, _extends2["default"])({}, props, {
116
+ Component: _MoneyFormattedInput.MoneyFormattedInput
117
+ }));
118
+
112
119
  default:
113
120
  return /*#__PURE__*/_react["default"].createElement(_FormGroupWrapper["default"], (0, _extends2["default"])({}, props, {
114
121
  Component: DefaultInput
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports["default"] = MoneyFormattedInput;
11
+
12
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
+
14
+ var _react = _interopRequireWildcard(require("react"));
15
+
16
+ var _formik = require("formik");
17
+
18
+ var _debounce = _interopRequireDefault(require("lodash/debounce"));
19
+
20
+ var _classnames = _interopRequireDefault(require("classnames"));
21
+
22
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
23
+
24
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
+
26
+ // Money input that will format the value to always have commas, a single decimal, and
27
+ // exactly two digits after the decimal. This happens after a delay (using debounce).
28
+ function MoneyFormattedInput(_ref) {
29
+ var name = _ref.name,
30
+ onBlur = _ref.onBlur,
31
+ onChange = _ref.onChange,
32
+ classname = _ref.classname,
33
+ _ref$disabled = _ref.disabled,
34
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
35
+ _ref$debounceTimer = _ref.debounceTimer,
36
+ debounceTimer = _ref$debounceTimer === void 0 ? 1500 : _ref$debounceTimer,
37
+ meta = _ref.meta;
38
+
39
+ // The displayed state and formik state are two seperate values that we handle
40
+ var _useState = (0, _react.useState)(''),
41
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
42
+ inputValue = _useState2[0],
43
+ setInputValue = _useState2[1];
44
+
45
+ var _useField = (0, _formik.useField)(name),
46
+ _useField2 = (0, _slicedToArray2["default"])(_useField, 1),
47
+ formikValue = _useField2[0].value;
48
+
49
+ var handleChangeDebounce = (0, _react.useMemo)(function () {
50
+ return (0, _debounce["default"])(debouncedUpdateInput, debounceTimer);
51
+
52
+ function debouncedUpdateInput(value) {
53
+ var result = formatToCurrency(value);
54
+ setInputValue(result !== null && result !== void 0 ? result : ''); // sets value in formik
55
+
56
+ onChange(result !== null && result !== void 0 ? result : '');
57
+ onBlur();
58
+ }
59
+ }, [onBlur, onChange]); // Format first render
60
+
61
+ (0, _react.useEffect)(function () {
62
+ var formattedFormikValue = formatToCurrency(formikValue);
63
+ setInputValue(formattedFormikValue !== null && formattedFormikValue !== void 0 ? formattedFormikValue : '');
64
+ }, [formikValue]);
65
+
66
+ function handleChange(e) {
67
+ var onlyNumbersDecimalComma = e.target.value.toString().replace(/[^.,0-9]/g, '');
68
+ setInputValue(onlyNumbersDecimalComma);
69
+ handleChangeDebounce(onlyNumbersDecimalComma);
70
+ }
71
+
72
+ return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("div", {
73
+ className: "input-group"
74
+ }, /*#__PURE__*/_react["default"].createElement("div", {
75
+ className: "input-group-prepend"
76
+ }, /*#__PURE__*/_react["default"].createElement("span", {
77
+ className: "input-group-text"
78
+ }, "$")), /*#__PURE__*/_react["default"].createElement("input", {
79
+ name: name,
80
+ type: "text",
81
+ value: inputValue,
82
+ onChange: handleChange,
83
+ onBlur: onBlur,
84
+ disabled: disabled,
85
+ className: (0, _classnames["default"])(classname, meta.error === 'Required' ? 'is-invalid' : '', 'react-select-input money-input form-control')
86
+ })));
87
+ }
88
+
89
+ function formatToCurrency(value) {
90
+ if (value === null || value === undefined) {
91
+ return null;
92
+ } // 'value' is sometimes a number on first render
93
+
94
+
95
+ var onlyNumbersDecimal = value.toString().replace(/[^.0-9]/g, '');
96
+
97
+ if (!onlyNumbersDecimal) {
98
+ return null;
99
+ }
100
+
101
+ var result = new Intl.NumberFormat('en-US', {
102
+ style: 'decimal',
103
+ minimumSignificantDigits: 2,
104
+ minimumFractionDigits: 2
105
+ }).format(parseFloat(onlyNumbersDecimal));
106
+ result = formatTwoDecimalPlaces(result);
107
+ return result;
108
+ }
109
+
110
+ function formatTwoDecimalPlaces(value) {
111
+ var decimalIndex = value.indexOf('.'); // If the string doesn't contain a decimal OR
112
+ // the string contains a single '.' with nothing to the right of the decimal -> append '.00'
113
+ // Reason: parseFloat will remove '.00' from whole numbers (ex. 350.00 -> 350)
114
+
115
+ if (!value.includes('.')) {
116
+ return value.concat('.00');
117
+ } // If 2 or more characters to the right of the decimal
118
+ else if (!!value.charAt(decimalIndex + 2)) {
119
+ return value.substring(0, decimalIndex + 3);
120
+ } // If only 1 character to the right of the decimal
121
+ else if (!!value.charAt(decimalIndex + 1)) {
122
+ return value.substring(0, decimalIndex + 2).concat('0');
123
+ }
124
+
125
+ return value;
126
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ Object.defineProperty(exports, "MoneyFormattedInput", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _MoneyFormattedInput["default"];
12
+ }
13
+ });
14
+
15
+ var _MoneyFormattedInput = _interopRequireDefault(require("./MoneyFormattedInput"));
package/lib/index.js CHANGED
@@ -31,12 +31,24 @@ Object.defineProperty(exports, "MoneyInput", {
31
31
  return _MoneyInput.MoneyInput;
32
32
  }
33
33
  });
34
+ Object.defineProperty(exports, "MoneyFormattedInput", {
35
+ enumerable: true,
36
+ get: function get() {
37
+ return _MoneyFormattedInput.MoneyFormattedInput;
38
+ }
39
+ });
34
40
  Object.defineProperty(exports, "AddressInput", {
35
41
  enumerable: true,
36
42
  get: function get() {
37
43
  return _AddressInput["default"];
38
44
  }
39
45
  });
46
+ Object.defineProperty(exports, "UsStates", {
47
+ enumerable: true,
48
+ get: function get() {
49
+ return _AddressInput.UsStates;
50
+ }
51
+ });
40
52
  Object.defineProperty(exports, "ConfirmBaseForm", {
41
53
  enumerable: true,
42
54
  get: function get() {
@@ -49,18 +61,60 @@ Object.defineProperty(exports, "ConfirmDeleteForm", {
49
61
  return _ConfirmDeleteForm["default"];
50
62
  }
51
63
  });
64
+ Object.defineProperty(exports, "DatePickerInput", {
65
+ enumerable: true,
66
+ get: function get() {
67
+ return _DatePickerInput["default"];
68
+ }
69
+ });
52
70
  Object.defineProperty(exports, "ErrorScrollTarget", {
53
71
  enumerable: true,
54
72
  get: function get() {
55
73
  return _ErrorScrollTarget["default"];
56
74
  }
57
75
  });
76
+ Object.defineProperty(exports, "FileInput", {
77
+ enumerable: true,
78
+ get: function get() {
79
+ return _FileInput.FileInput;
80
+ }
81
+ });
82
+ Object.defineProperty(exports, "DropzoneFileInput", {
83
+ enumerable: true,
84
+ get: function get() {
85
+ return _FileInput.DropzoneFileInput;
86
+ }
87
+ });
88
+ Object.defineProperty(exports, "DefaultFileList", {
89
+ enumerable: true,
90
+ get: function get() {
91
+ return _FileInput.DefaultFileList;
92
+ }
93
+ });
58
94
  Object.defineProperty(exports, "Form", {
59
95
  enumerable: true,
60
96
  get: function get() {
61
97
  return _Form["default"];
62
98
  }
63
99
  });
100
+ Object.defineProperty(exports, "ServerErrorContext", {
101
+ enumerable: true,
102
+ get: function get() {
103
+ return _Form.ServerErrorContext;
104
+ }
105
+ });
106
+ Object.defineProperty(exports, "FocusError", {
107
+ enumerable: true,
108
+ get: function get() {
109
+ return _Form.FocusError;
110
+ }
111
+ });
112
+ Object.defineProperty(exports, "FormBasedPreventNavigation", {
113
+ enumerable: true,
114
+ get: function get() {
115
+ return _Form.FormBasedPreventNavigation;
116
+ }
117
+ });
64
118
  Object.defineProperty(exports, "FormGroup", {
65
119
  enumerable: true,
66
120
  get: function get() {
@@ -127,6 +181,30 @@ Object.defineProperty(exports, "validators", {
127
181
  return _validators["default"];
128
182
  }
129
183
  });
184
+ Object.defineProperty(exports, "ReactSelectField", {
185
+ enumerable: true,
186
+ get: function get() {
187
+ return _ReactSelectField["default"];
188
+ }
189
+ });
190
+ Object.defineProperty(exports, "customReactSelectFieldStyles", {
191
+ enumerable: true,
192
+ get: function get() {
193
+ return _ReactSelectField.customStyles;
194
+ }
195
+ });
196
+ Object.defineProperty(exports, "overrideReactSelectFieldStyles", {
197
+ enumerable: true,
198
+ get: function get() {
199
+ return _ReactSelectField.overrideTheme;
200
+ }
201
+ });
202
+ Object.defineProperty(exports, "NestedFormFieldContext", {
203
+ enumerable: true,
204
+ get: function get() {
205
+ return _NestedFormFieldContext["default"];
206
+ }
207
+ });
130
208
  exports.normalizers = void 0;
131
209
 
132
210
  var normalizers = _interopRequireWildcard(require("./normalizers"));
@@ -137,15 +215,21 @@ var _BoolInput = require("./BoolInput");
137
215
 
138
216
  var _MoneyInput = require("./MoneyInput");
139
217
 
140
- var _AddressInput = _interopRequireDefault(require("./AddressInput"));
218
+ var _MoneyFormattedInput = require("./MoneyFormattedInput");
219
+
220
+ var _AddressInput = _interopRequireWildcard(require("./AddressInput"));
141
221
 
142
222
  var _ConfirmBaseForm = _interopRequireDefault(require("./ConfirmBaseForm"));
143
223
 
144
224
  var _ConfirmDeleteForm = _interopRequireDefault(require("./ConfirmDeleteForm"));
145
225
 
226
+ var _DatePickerInput = _interopRequireDefault(require("./DatePickerInput"));
227
+
146
228
  var _ErrorScrollTarget = _interopRequireDefault(require("./ErrorScrollTarget"));
147
229
 
148
- var _Form = _interopRequireDefault(require("./Form"));
230
+ var _FileInput = require("./FileInput");
231
+
232
+ var _Form = _interopRequireWildcard(require("./Form"));
149
233
 
150
234
  var _FormGroup = _interopRequireDefault(require("./FormGroup"));
151
235
 
@@ -169,6 +253,10 @@ var _useStandardFormInput = _interopRequireDefault(require("./useStandardFormInp
169
253
 
170
254
  var _validators = _interopRequireDefault(require("./validators"));
171
255
 
256
+ var _ReactSelectField = _interopRequireWildcard(require("./ReactSelectField"));
257
+
258
+ var _NestedFormFieldContext = _interopRequireDefault(require("./NestedFormFieldContext"));
259
+
172
260
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
173
261
 
174
262
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -82,7 +82,7 @@ function minCount(count) {
82
82
 
83
83
  var maxValue = function maxValue(value) {
84
84
  return function (inputValue) {
85
- if (inputValue && value) {
85
+ if (inputValue != null && value != null) {
86
86
  return inputValue <= value ? undefined : "Maximum value ".concat(value, " exceeded");
87
87
  } else {
88
88
  return undefined;
@@ -94,7 +94,7 @@ exports.maxValue = maxValue;
94
94
 
95
95
  var minValue = function minValue(value) {
96
96
  return function (inputValue) {
97
- if (inputValue && value) {
97
+ if (inputValue != null && value != null) {
98
98
  return inputValue >= value ? undefined : "Minimum value ".concat(value, " not met");
99
99
  } else {
100
100
  return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envoc-form",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Envoc form components",
5
5
  "keywords": [
6
6
  "react-component",
@@ -26,7 +26,8 @@
26
26
  "axios": "^0.21.1",
27
27
  "classnames": "^2.3.1",
28
28
  "date-fns": "^2.22.1",
29
- "envoc-request": "^3.2.0",
29
+ "envoc-request": "^3.3.0",
30
+ "lodash": "^4.17.21",
30
31
  "lru-cache": "^6.0.0",
31
32
  "prop-types": "^15.7.2",
32
33
  "react-date-picker": "^8.2.0",
@@ -1,2 +1,3 @@
1
1
  import AddressInput from './AddressInput';
2
- export default AddressInput;
2
+ import UsStates from './UsStates';
3
+ export { AddressInput as default, UsStates };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import DatePicker from 'react-date-picker';
2
+ import DatePicker from 'react-date-picker/dist/entry.nostyle';
3
3
  import parseISO from 'date-fns/parseISO';
4
4
  import classnames from 'classnames';
5
5
 
@@ -1,4 +1,5 @@
1
1
  import FileInput from './FileInput';
2
2
  import DropzoneFileInput from './DropzoneFileInput';
3
+ import DefaultFileList from './DefaultFileList';
3
4
 
4
- export { FileInput, DropzoneFileInput };
5
+ export { FileInput, DropzoneFileInput, DefaultFileList };
package/src/Form/index.js CHANGED
@@ -1,3 +1,11 @@
1
+ import FocusError from './FocusError';
1
2
  import Form from './Form';
3
+ import FormBasedPreventNavigation from './FormBasedPreventNavigation';
2
4
  import ServerErrorContext from './ServerErrorContext';
3
- export { Form as default, ServerErrorContext };
5
+
6
+ export {
7
+ Form as default,
8
+ ServerErrorContext,
9
+ FocusError,
10
+ FormBasedPreventNavigation,
11
+ };
@@ -15,6 +15,7 @@ import FormGroupWrapper from '../FormGroupWrapper';
15
15
  import DatePickerInput from '../DatePickerInput';
16
16
  import ReactSelectField from '../ReactSelectField';
17
17
  import useStandardFormInput from '../useStandardFormInput';
18
+ import { MoneyFormattedInput } from '../MoneyFormattedInput';
18
19
  import { FileInput, DropzoneFileInput } from '../FileInput';
19
20
 
20
21
  export default function FormInput(props) {
@@ -57,6 +58,8 @@ function StandardFieldGroup(props) {
57
58
  return <FormGroupWrapper {...props} Component={FileInput} />;
58
59
  case 'textarea':
59
60
  return <FormGroupWrapper {...props} Component={TextAreaInput} />;
61
+ case 'moneyFormatted':
62
+ return <FormGroupWrapper {...props} Component={MoneyFormattedInput} />;
60
63
  default:
61
64
  return <FormGroupWrapper {...props} Component={DefaultInput} />;
62
65
  }
@@ -0,0 +1,115 @@
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+ import { useField } from 'formik';
3
+ import debounce from 'lodash/debounce';
4
+ import classNames from 'classnames';
5
+
6
+ // Money input that will format the value to always have commas, a single decimal, and
7
+ // exactly two digits after the decimal. This happens after a delay (using debounce).
8
+ export default function MoneyFormattedInput({
9
+ name,
10
+ onBlur,
11
+ onChange,
12
+ classname,
13
+ disabled = false,
14
+ debounceTimer = 1500,
15
+ meta,
16
+ }) {
17
+ // The displayed state and formik state are two seperate values that we handle
18
+ const [inputValue, setInputValue] = useState('');
19
+ const [{ value: formikValue }] = useField(name);
20
+
21
+ const handleChangeDebounce = useMemo(() => {
22
+ return debounce(debouncedUpdateInput, debounceTimer);
23
+
24
+ function debouncedUpdateInput(value) {
25
+ var result = formatToCurrency(value);
26
+
27
+ setInputValue(result ?? '');
28
+
29
+ // sets value in formik
30
+ onChange(result ?? '');
31
+ onBlur();
32
+ }
33
+ }, [onBlur, onChange]);
34
+
35
+ // Format first render
36
+ useEffect(() => {
37
+ var formattedFormikValue = formatToCurrency(formikValue);
38
+ setInputValue(formattedFormikValue ?? '');
39
+ }, [formikValue]);
40
+
41
+ function handleChange(e) {
42
+ const onlyNumbersDecimalComma = e.target.value
43
+ .toString()
44
+ .replace(/[^.,0-9]/g, '');
45
+
46
+ setInputValue(onlyNumbersDecimalComma);
47
+ handleChangeDebounce(onlyNumbersDecimalComma);
48
+ }
49
+
50
+ return (
51
+ <>
52
+ <div className="input-group">
53
+ <div className="input-group-prepend">
54
+ <span className="input-group-text">$</span>
55
+ </div>
56
+ <input
57
+ name={name}
58
+ type="text"
59
+ value={inputValue}
60
+ onChange={handleChange}
61
+ onBlur={onBlur}
62
+ disabled={disabled}
63
+ className={classNames(
64
+ classname,
65
+ meta.error === 'Required' ? 'is-invalid' : '',
66
+ 'react-select-input money-input form-control'
67
+ )}
68
+ />
69
+ </div>
70
+ </>
71
+ );
72
+ }
73
+
74
+ function formatToCurrency(value) {
75
+ if (value === null || value === undefined) {
76
+ return null;
77
+ }
78
+
79
+ // 'value' is sometimes a number on first render
80
+ const onlyNumbersDecimal = value.toString().replace(/[^.0-9]/g, '');
81
+
82
+ if (!onlyNumbersDecimal) {
83
+ return null;
84
+ }
85
+
86
+ var result = new Intl.NumberFormat('en-US', {
87
+ style: 'decimal',
88
+ minimumSignificantDigits: 2,
89
+ minimumFractionDigits: 2,
90
+ }).format(parseFloat(onlyNumbersDecimal));
91
+
92
+ result = formatTwoDecimalPlaces(result);
93
+ return result;
94
+ }
95
+
96
+ function formatTwoDecimalPlaces(value) {
97
+ const decimalIndex = value.indexOf('.');
98
+
99
+ // If the string doesn't contain a decimal OR
100
+ // the string contains a single '.' with nothing to the right of the decimal -> append '.00'
101
+ // Reason: parseFloat will remove '.00' from whole numbers (ex. 350.00 -> 350)
102
+ if (!value.includes('.')) {
103
+ return value.concat('.00');
104
+ }
105
+ // If 2 or more characters to the right of the decimal
106
+ else if (!!value.charAt(decimalIndex + 2)) {
107
+ return value.substring(0, decimalIndex + 3);
108
+ }
109
+ // If only 1 character to the right of the decimal
110
+ else if (!!value.charAt(decimalIndex + 1)) {
111
+ return value.substring(0, decimalIndex + 2).concat('0');
112
+ }
113
+
114
+ return value;
115
+ }
@@ -0,0 +1,3 @@
1
+ import MoneyFormattedInput from './MoneyFormattedInput';
2
+
3
+ export { MoneyFormattedInput };
package/src/index.js CHANGED
@@ -2,12 +2,19 @@ import * as normalizers from './normalizers';
2
2
 
3
3
  import { BoolInput, InlineBoolInput } from './BoolInput';
4
4
  import { InlineMoneyInput, MoneyInput } from './MoneyInput';
5
+ import { MoneyFormattedInput } from './MoneyFormattedInput';
5
6
 
6
- import AddressInput from './AddressInput';
7
+ import AddressInput, { UsStates } from './AddressInput';
7
8
  import ConfirmBaseForm from './ConfirmBaseForm';
8
9
  import ConfirmDeleteForm from './ConfirmDeleteForm';
10
+ import DatePickerInput from './DatePickerInput';
9
11
  import ErrorScrollTarget from './ErrorScrollTarget';
10
- import Form from './Form';
12
+ import { FileInput, DropzoneFileInput, DefaultFileList } from './FileInput';
13
+ import Form, {
14
+ ServerErrorContext,
15
+ FocusError,
16
+ FormBasedPreventNavigation,
17
+ } from './Form';
11
18
  import FormGroup from './FormGroup';
12
19
  import FormGroupWrapper from './FormGroupWrapper';
13
20
  import FormInput from './FormInput';
@@ -19,13 +26,23 @@ import StandardFormActions from './StandardFormActions';
19
26
  import SubmitFormButton from './SubmitFormButton';
20
27
  import useStandardFormInput from './useStandardFormInput';
21
28
  import validators from './validators';
29
+ import ReactSelectField, {
30
+ customStyles as customReactSelectFieldStyles,
31
+ overrideTheme as overrideReactSelectFieldStyles,
32
+ } from './ReactSelectField';
33
+ import NestedFormFieldContext from './NestedFormFieldContext';
22
34
 
23
35
  export {
24
36
  AddressInput,
37
+ UsStates,
25
38
  BoolInput,
26
39
  ConfirmBaseForm,
27
40
  ConfirmDeleteForm,
41
+ DatePickerInput,
28
42
  ErrorScrollTarget,
43
+ FileInput,
44
+ DropzoneFileInput,
45
+ DefaultFileList,
29
46
  Form,
30
47
  FormGroup,
31
48
  FormGroupWrapper,
@@ -37,9 +54,17 @@ export {
37
54
  InlineFormInput,
38
55
  InlineMoneyInput,
39
56
  MoneyInput,
57
+ MoneyFormattedInput,
40
58
  normalizers,
41
59
  StandardFormActions,
42
60
  SubmitFormButton,
43
61
  useStandardFormInput,
44
62
  validators,
63
+ ServerErrorContext,
64
+ FocusError,
65
+ FormBasedPreventNavigation,
66
+ ReactSelectField,
67
+ customReactSelectFieldStyles,
68
+ overrideReactSelectFieldStyles,
69
+ NestedFormFieldContext,
45
70
  };
@@ -55,7 +55,7 @@ export function minCount(count) {
55
55
 
56
56
  export const maxValue = function maxValue(value) {
57
57
  return (inputValue) => {
58
- if (inputValue && value) {
58
+ if (inputValue != null && value != null) {
59
59
  return inputValue <= value
60
60
  ? undefined
61
61
  : `Maximum value ${value} exceeded`;
@@ -67,7 +67,7 @@ export const maxValue = function maxValue(value) {
67
67
 
68
68
  export const minValue = function minValue(value) {
69
69
  return (inputValue) => {
70
- if (inputValue && value) {
70
+ if (inputValue != null && value != null) {
71
71
  return inputValue >= value ? undefined : `Minimum value ${value} not met`;
72
72
  } else {
73
73
  return undefined;