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
|
-
|
|
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 };
|