pcm-shared-components 0.0.173 → 0.0.174

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.
@@ -0,0 +1,256 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { ThemeProvider } from '@mui/system';
4
+ import { createTheme, useTheme } from '@mui/material/styles';
5
+ import FormControl from '@mui/material/FormControl';
6
+ import InputLabel from '@mui/material/InputLabel';
7
+ import Input from '@mui/material/Input';
8
+ import { InputAdornment } from '@mui/material';
9
+ import TextField from '@mui/material/TextField';
10
+ let debounce;
11
+ /**
12
+ * ## Importing the component in your project
13
+ *
14
+ ```js
15
+
16
+ import {CurrencyTextInput} from 'pcm-shared-components';
17
+
18
+ ```
19
+ *
20
+ */
21
+
22
+ export const CurrencyTextInput = props => {
23
+ const {
24
+ value,
25
+ label,
26
+ variant,
27
+ fullWidth,
28
+ onChange,
29
+ onChangeDebounce,
30
+ currencySymbol,
31
+ className,
32
+ decimalPlaces,
33
+ maximumValue,
34
+ minimumValue,
35
+ textAlign,
36
+ useThousandSeparator,
37
+ fontSize,
38
+ textPadding,
39
+ theme
40
+ } = props;
41
+ const compTheme = theme ? theme : useTheme();
42
+ const defaultTheme = createTheme(compTheme); //Hooks
43
+
44
+ const [localValue, setLocalValue] = useState(value);
45
+ useEffect(() => {
46
+ clearTimeout(debounce);
47
+ debounce = setTimeout(() => {
48
+ onChangeDebounce(localValue);
49
+ }, 700);
50
+ }, [localValue]); //---------------------------------------------------
51
+ // Functions used to sanitize the number
52
+ //---------------------------------------------------
53
+
54
+ const sanitizeDecimalDots = value => {
55
+ //Ensures we only have one decimal dot in our number
56
+ try {
57
+ return String(value).replace(/[.](?=.*[.])/g, "");
58
+ } catch (error) {
59
+ console.error(error);
60
+ }
61
+
62
+ return value;
63
+ };
64
+
65
+ const sanitizeDigits = value => {
66
+ //Ensures we only have digits in our number
67
+ try {
68
+ //Allow normal numbers, negative number and dots
69
+ const isNegativeNumber = value[0] === '-';
70
+ let returnVal = String(value).replace(/[^\d.]/gi, '');
71
+ return `${isNegativeNumber ? '-' : ''}${returnVal}`; //Only allow numbers and dots
72
+ // return String(value).replace(/[^\d.]/gi, '');
73
+ } catch (error) {
74
+ console.error(error);
75
+ }
76
+
77
+ return value;
78
+ };
79
+
80
+ const sanitizeDecimalPlaces = value => {
81
+ try {
82
+ // Only apply this rule if we have a decimal place with something in it or else skip because it's causing inconsistent number formatting when entering the digits
83
+ const decimalCheck = String(value).split('.');
84
+
85
+ if (decimalCheck.length === 2 && decimalCheck[1].length > 0) {
86
+ return Number(value).toLocaleString(undefined, {
87
+ minimumFractionDigits: 1,
88
+ maximumFractionDigits: decimalPlaces,
89
+ useGrouping: false
90
+ });
91
+ }
92
+ } catch (error) {
93
+ console.error(error);
94
+ }
95
+
96
+ return value;
97
+ };
98
+
99
+ const sanitizeMinMaxValues = value => {
100
+ try {
101
+ if (!isNaN(value)) {
102
+ if (Number(value) > maximumValue) {
103
+ return maximumValue;
104
+ }
105
+
106
+ if (Number(value) < minimumValue) {
107
+ return minimumValue;
108
+ }
109
+ }
110
+ } catch (error) {
111
+ console.error(error);
112
+ }
113
+
114
+ return value;
115
+ };
116
+
117
+ const sanitizeThousandPlaces = value => {
118
+ try {
119
+ // Only apply the thousand grouping on the numbers before the decimal
120
+ if (useThousandSeparator && !isNaN(value)) {
121
+ const digits = String(value).split('.');
122
+
123
+ if (digits[0].length > 0) {
124
+ const thousandFormatted = Number(digits[0]).toLocaleString(undefined, {
125
+ useGrouping: true
126
+ });
127
+
128
+ if (digits.length === 2) {
129
+ //Let's keep any additional DOT and decimal places even if they are empty
130
+ return `${thousandFormatted}.${digits[1]}`;
131
+ } else {
132
+ return thousandFormatted;
133
+ }
134
+ }
135
+ }
136
+ } catch (error) {
137
+ console.error(error);
138
+ }
139
+
140
+ return value;
141
+ };
142
+
143
+ const handleCurrencyFormatting = value => {
144
+ let returnVal = value;
145
+
146
+ try {
147
+ returnVal = sanitizeMinMaxValues(returnVal);
148
+ returnVal = sanitizeDecimalDots(returnVal);
149
+ returnVal = sanitizeDigits(returnVal);
150
+ returnVal = sanitizeDecimalPlaces(returnVal);
151
+ returnVal = sanitizeThousandPlaces(returnVal);
152
+ } catch (error) {
153
+ console.error(error);
154
+ }
155
+
156
+ return returnVal;
157
+ };
158
+
159
+ const handleOnChange = event => {
160
+ setLocalValue(event.target.value);
161
+ onChange(event.target.value);
162
+ };
163
+
164
+ return /*#__PURE__*/React.createElement(ThemeProvider, {
165
+ theme: defaultTheme
166
+ }, /*#__PURE__*/React.createElement(TextField, {
167
+ id: "input-with-icon-textfield",
168
+ className: ` ${className}`,
169
+ fullWidth: fullWidth,
170
+ label: label,
171
+ value: handleCurrencyFormatting(value),
172
+ onChange: handleOnChange,
173
+ inputProps: {
174
+ autoComplete: "new-password",
175
+ style: {
176
+ textAlign: textAlign,
177
+ fontSize: fontSize,
178
+ padding: textPadding
179
+ }
180
+ },
181
+ InputProps: {
182
+ startAdornment: /*#__PURE__*/React.createElement(InputAdornment, {
183
+ position: "start"
184
+ }, currencySymbol)
185
+ },
186
+ variant: variant
187
+ }));
188
+ };
189
+ export default CurrencyTextInput;
190
+ CurrencyTextInput.defaultProps = {
191
+ value: 0,
192
+ label: 'Some Label',
193
+ variant: 'outlined',
194
+ fullWidth: true,
195
+ onChange: () => {},
196
+ onChangeDebounce: () => {},
197
+ currencySymbol: '$',
198
+ useThousandSeparator: true,
199
+ className: '',
200
+ decimalPlaces: 2,
201
+ maximumValue: 10000000000000,
202
+ minimumValue: -10000000000000,
203
+ textAlign: 'right',
204
+ fontSize: 16,
205
+ textPadding: 4,
206
+ theme: undefined
207
+ };
208
+ CurrencyTextInput.propTypes = {
209
+ /** Value to be enter and display in input */
210
+ value: PropTypes.string,
211
+
212
+ /** The label content*/
213
+ label: PropTypes.string,
214
+
215
+ /** Controls the look of the text field*/
216
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard']),
217
+
218
+ /** Determines if the text field will be full width or fit content*/
219
+ fullWidth: PropTypes.bool,
220
+
221
+ /** Determines if the final number grouping will contain the thousand separator */
222
+ useThousandSeparator: PropTypes.bool,
223
+
224
+ /** Callback fired when the value is changed*/
225
+ onChange: PropTypes.func,
226
+
227
+ /** Same as onChange except only fires 700ms after the users has completed typing to prevent performance issues. Returns the new value */
228
+ onChangeDebounce: PropTypes.func,
229
+
230
+ /** Defines the currency symbol string.*/
231
+ currencySymbol: PropTypes.string,
232
+
233
+ /** Classes to add to the wrapper control*/
234
+ className: PropTypes.string,
235
+
236
+ /** Controls the font size in in pt example: 14*/
237
+ fontSize: PropTypes.number,
238
+
239
+ /** Controls the padding around the font */
240
+ textPadding: PropTypes.number,
241
+
242
+ /** Defines the default number of decimal places to show on the formatted value.*/
243
+ decimalPlaces: PropTypes.number,
244
+
245
+ /** Maximum value that can be enter*/
246
+ maximumValue: PropTypes.number,
247
+
248
+ /** Minimum value that can be entered*/
249
+ minimumValue: PropTypes.number,
250
+
251
+ /** Align the numbers in the textField.*/
252
+ textAlign: PropTypes.oneOf(['left', 'right']),
253
+
254
+ /** Theme object to use on this component, if none provided then the MUI5 theme provider theme is used*/
255
+ theme: PropTypes.object
256
+ };
package/dist/index.js CHANGED
@@ -20,4 +20,5 @@ import coreLocals from './locals/coreLocals';
20
20
  import currencySymbol from './locals/currencySymbol';
21
21
  import DateRangeCalendar from './components/Date/DateRangeCalendar';
22
22
  import SimpleLabel from './components/Labels/SimpleLabel';
23
- export { TestButton, CodeHighlight, CustomFab, HelpButton, GenericDialogWindow, PcSharedComponentThemeInheritor, ImageCanvasDraw, PCMScrollbar, TwoColumnDisplay, SimpleTab, HrefLink, GenericAppBar, ReusablePopupMenu, SearchBar, TillButton, DropdownButton, translationResources, coreLocals, currencySymbol, DateRangeCalendar, SimpleLabel };
23
+ import CurrencyTextInput from './components/TextBoxes/CurrencyTextInput';
24
+ export { TestButton, CodeHighlight, CustomFab, HelpButton, GenericDialogWindow, PcSharedComponentThemeInheritor, ImageCanvasDraw, PCMScrollbar, TwoColumnDisplay, SimpleTab, HrefLink, GenericAppBar, ReusablePopupMenu, SearchBar, TillButton, DropdownButton, translationResources, coreLocals, currencySymbol, DateRangeCalendar, SimpleLabel, CurrencyTextInput };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pcm-shared-components",
3
- "version": "0.0.173",
3
+ "version": "0.0.174",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "babel": {