envoc-form 3.0.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.
Files changed (34) hide show
  1. package/es/AddressInput/index.js +2 -1
  2. package/es/DatePickerInput/DatePickerInput.js +1 -1
  3. package/es/FileInput/index.js +2 -1
  4. package/es/Form/index.js +3 -1
  5. package/es/FormInput/FormInput.js +6 -0
  6. package/es/MoneyFormattedInput/MoneyFormattedInput.js +106 -0
  7. package/es/MoneyFormattedInput/index.js +2 -0
  8. package/es/ReactSelectField/ReactSelectField.js +36 -2
  9. package/es/index.js +20 -10
  10. package/es/validators/validators.js +2 -2
  11. package/lib/AddressInput/index.js +13 -3
  12. package/lib/DatePickerInput/DatePickerInput.js +2 -2
  13. package/lib/FileInput/index.js +9 -1
  14. package/lib/Form/index.js +16 -0
  15. package/lib/FormInput/FormInput.js +7 -0
  16. package/lib/MoneyFormattedInput/MoneyFormattedInput.js +126 -0
  17. package/lib/MoneyFormattedInput/index.js +15 -0
  18. package/lib/ReactSelectField/ReactSelectField.js +37 -2
  19. package/lib/index.js +166 -38
  20. package/lib/validators/validators.js +2 -2
  21. package/package.json +3 -2
  22. package/src/AddressInput/__snapshots__/AddesssInput.test.js.snap +1 -1
  23. package/src/AddressInput/index.js +2 -1
  24. package/src/BoolInput/__snapshots__/BoolInput.test.js.snap +1 -1
  25. package/src/DatePickerInput/DatePickerInput.js +1 -1
  26. package/src/FileInput/index.js +2 -1
  27. package/src/Form/index.js +9 -1
  28. package/src/FormInput/FormInput.js +3 -0
  29. package/src/FormInput/__snapshots__/FormInput.test.js.snap +1 -1
  30. package/src/MoneyFormattedInput/MoneyFormattedInput.js +115 -0
  31. package/src/MoneyFormattedInput/index.js +3 -0
  32. package/src/ReactSelectField/ReactSelectField.js +34 -1
  33. package/src/index.js +54 -17
  34. package/src/validators/validators.js +2 -2
@@ -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 };
@@ -7,6 +7,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
7
7
 
8
8
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
9
9
 
10
+ import classNames from 'classnames';
10
11
  import React, { useEffect, useRef } from 'react';
11
12
  import { default as ReactSelect } from 'react-select';
12
13
  export var overrideTheme = function overrideTheme(theme) {
@@ -22,6 +23,8 @@ var red = '#f86c6b';
22
23
  var inputBorderColor = '#c2cfd6';
23
24
  var inputBorderColorFocused = '#8ad4ee';
24
25
  var inputBoxShadowFocused = '0 0 0 0.2rem rgba(32, 168, 216, 0.25)';
26
+ var placeholderColor = '#9ca3af';
27
+ var disabledSingleValueColor = '#4b5563';
25
28
  export var customStyles = {
26
29
  control: function control(provided, _ref) {
27
30
  var isFocused = _ref.isFocused,
@@ -39,6 +42,17 @@ export var customStyles = {
39
42
  return _objectSpread(_objectSpread({}, provided), {}, {
40
43
  zIndex: 3
41
44
  });
45
+ },
46
+ singleValue: function singleValue(provided, state) {
47
+ var color = state.isDisabled ? disabledSingleValueColor : '';
48
+ return _objectSpread(_objectSpread({}, provided), {}, {
49
+ color: color
50
+ });
51
+ },
52
+ placeholder: function placeholder(defaultStyles) {
53
+ return _objectSpread(_objectSpread({}, defaultStyles), {}, {
54
+ color: placeholderColor
55
+ });
42
56
  }
43
57
  }; // internal to forms use only
44
58
 
@@ -48,7 +62,7 @@ export default function ReactSelectInput(_ref2) {
48
62
  disabled = _ref2.disabled,
49
63
  onSelected = _ref2.onSelected,
50
64
  onChange = _ref2.onChange,
51
- onBlur = _ref2.onBlur,
65
+ _onBlur = _ref2.onBlur,
52
66
  value = _ref2.value,
53
67
  options = _ref2.options,
54
68
  defaultValue = _ref2.defaultValue,
@@ -61,6 +75,23 @@ export default function ReactSelectInput(_ref2) {
61
75
  useEffect(function () {
62
76
  onSelectedRef.current && onSelectedRef.current(selectedItems);
63
77
  }, [selectedItems]);
78
+ var onBlurRef = useRef(_onBlur);
79
+ onBlurRef.current = _onBlur;
80
+ var touched = meta.touched;
81
+ useEffect(function () {
82
+ if (!touched) return; // without the timer set to 0, if the empty option is selected the required message doesn't appear until clicked away from the select input
83
+
84
+ var timerRef = setTimeout(function () {
85
+ onBlurRef.current && onBlurRef.current();
86
+ }, 0);
87
+ return function () {
88
+ clearTimeout(timerRef);
89
+ };
90
+ }, [value, touched]);
91
+ var classes = classNames(className, 'react-select-input', {
92
+ 'is-invalid': !!meta.error,
93
+ disabled: disabled
94
+ });
64
95
  return /*#__PURE__*/React.createElement(ReactSelect, _extends({}, props, {
65
96
  options: options,
66
97
  isDisabled: disabled,
@@ -71,7 +102,10 @@ export default function ReactSelectInput(_ref2) {
71
102
  getOptionValue: getOptionValue,
72
103
  value: selectedItems,
73
104
  onChange: handleChange,
74
- className: "react-select-input",
105
+ onBlur: function onBlur() {
106
+ return _onBlur();
107
+ },
108
+ className: classes,
75
109
  theme: overrideTheme,
76
110
  styles: customStyles,
77
111
  menuPortalTarget: document.body,
package/es/index.js CHANGED
@@ -1,15 +1,25 @@
1
- import Form from './Form';
1
+ import * as normalizers from './normalizers';
2
+ import { BoolInput, InlineBoolInput } from './BoolInput';
3
+ import { InlineMoneyInput, MoneyInput } from './MoneyInput';
4
+ import { MoneyFormattedInput } from './MoneyFormattedInput';
5
+ import AddressInput, { UsStates } from './AddressInput';
6
+ import ConfirmBaseForm from './ConfirmBaseForm';
7
+ import ConfirmDeleteForm from './ConfirmDeleteForm';
8
+ import DatePickerInput from './DatePickerInput';
9
+ import ErrorScrollTarget from './ErrorScrollTarget';
10
+ import { FileInput, DropzoneFileInput, DefaultFileList } from './FileInput';
11
+ import Form, { ServerErrorContext, FocusError, FormBasedPreventNavigation } from './Form';
12
+ import FormGroup from './FormGroup';
13
+ import FormGroupWrapper from './FormGroupWrapper';
2
14
  import FormInput from './FormInput';
3
- import InlineFormInput from './InlineFormInput';
4
15
  import FormInputArray from './FormInputArray';
16
+ import FormSection from './FormSection';
5
17
  import IconInput from './IconInput';
6
- import { BoolInput, InlineBoolInput } from './BoolInput';
18
+ import InlineFormInput from './InlineFormInput';
7
19
  import StandardFormActions from './StandardFormActions';
8
- import validators from './validators';
9
- import * as normalizers from './normalizers';
10
- import ConfirmBaseForm from './ConfirmBaseForm';
11
- import ConfirmDeleteForm from './ConfirmDeleteForm';
12
20
  import SubmitFormButton from './SubmitFormButton';
13
- import AddressInput from './AddressInput';
14
- import { MoneyInput, InlineMoneyInput } from './MoneyInput';
15
- export { Form, FormInput, InlineFormInput, FormInputArray, IconInput, BoolInput, InlineBoolInput, validators, normalizers, StandardFormActions, ConfirmBaseForm, ConfirmDeleteForm, SubmitFormButton, AddressInput, MoneyInput, InlineMoneyInput };
21
+ import useStandardFormInput from './useStandardFormInput';
22
+ import validators from './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"));
@@ -16,6 +16,8 @@ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/h
16
16
 
17
17
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
18
18
 
19
+ var _classnames = _interopRequireDefault(require("classnames"));
20
+
19
21
  var _react = _interopRequireWildcard(require("react"));
20
22
 
21
23
  var _reactSelect = _interopRequireDefault(require("react-select"));
@@ -45,6 +47,8 @@ var red = '#f86c6b';
45
47
  var inputBorderColor = '#c2cfd6';
46
48
  var inputBorderColorFocused = '#8ad4ee';
47
49
  var inputBoxShadowFocused = '0 0 0 0.2rem rgba(32, 168, 216, 0.25)';
50
+ var placeholderColor = '#9ca3af';
51
+ var disabledSingleValueColor = '#4b5563';
48
52
  var customStyles = {
49
53
  control: function control(provided, _ref) {
50
54
  var isFocused = _ref.isFocused,
@@ -62,6 +66,17 @@ var customStyles = {
62
66
  return _objectSpread(_objectSpread({}, provided), {}, {
63
67
  zIndex: 3
64
68
  });
69
+ },
70
+ singleValue: function singleValue(provided, state) {
71
+ var color = state.isDisabled ? disabledSingleValueColor : '';
72
+ return _objectSpread(_objectSpread({}, provided), {}, {
73
+ color: color
74
+ });
75
+ },
76
+ placeholder: function placeholder(defaultStyles) {
77
+ return _objectSpread(_objectSpread({}, defaultStyles), {}, {
78
+ color: placeholderColor
79
+ });
65
80
  }
66
81
  }; // internal to forms use only
67
82
 
@@ -73,7 +88,7 @@ function ReactSelectInput(_ref2) {
73
88
  disabled = _ref2.disabled,
74
89
  onSelected = _ref2.onSelected,
75
90
  onChange = _ref2.onChange,
76
- onBlur = _ref2.onBlur,
91
+ _onBlur = _ref2.onBlur,
77
92
  value = _ref2.value,
78
93
  options = _ref2.options,
79
94
  defaultValue = _ref2.defaultValue,
@@ -85,6 +100,23 @@ function ReactSelectInput(_ref2) {
85
100
  (0, _react.useEffect)(function () {
86
101
  onSelectedRef.current && onSelectedRef.current(selectedItems);
87
102
  }, [selectedItems]);
103
+ var onBlurRef = (0, _react.useRef)(_onBlur);
104
+ onBlurRef.current = _onBlur;
105
+ var touched = meta.touched;
106
+ (0, _react.useEffect)(function () {
107
+ if (!touched) return; // without the timer set to 0, if the empty option is selected the required message doesn't appear until clicked away from the select input
108
+
109
+ var timerRef = setTimeout(function () {
110
+ onBlurRef.current && onBlurRef.current();
111
+ }, 0);
112
+ return function () {
113
+ clearTimeout(timerRef);
114
+ };
115
+ }, [value, touched]);
116
+ var classes = (0, _classnames["default"])(className, 'react-select-input', {
117
+ 'is-invalid': !!meta.error,
118
+ disabled: disabled
119
+ });
88
120
  return /*#__PURE__*/_react["default"].createElement(_reactSelect["default"], (0, _extends2["default"])({}, props, {
89
121
  options: options,
90
122
  isDisabled: disabled,
@@ -95,7 +127,10 @@ function ReactSelectInput(_ref2) {
95
127
  getOptionValue: getOptionValue,
96
128
  value: selectedItems,
97
129
  onChange: handleChange,
98
- className: "react-select-input",
130
+ onBlur: function onBlur() {
131
+ return _onBlur();
132
+ },
133
+ className: classes,
99
134
  theme: overrideTheme,
100
135
  styles: customStyles,
101
136
  menuPortalTarget: document.body,