@canutin/svelte-currency-input 0.7.0 → 0.7.2
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.
- package/CurrencyInput.svelte +37 -19
- package/README.md +17 -0
- package/package.json +1 -1
package/CurrencyInput.svelte
CHANGED
|
@@ -26,8 +26,9 @@ const handleKeyDown = (event) => {
|
|
|
26
26
|
const isDeletion = event.key === 'Backspace' || event.key === 'Delete';
|
|
27
27
|
const isModifier = event.metaKey || event.altKey || event.ctrlKey;
|
|
28
28
|
const isArrowKey = event.key === 'ArrowLeft' || event.key === 'ArrowRight';
|
|
29
|
+
const isTab = event.key === 'Tab';
|
|
29
30
|
const isInvalidCharacter = !/^\d|,|\.|-$/g.test(event.key); // Keys that are not a digit, comma, period or minus sign
|
|
30
|
-
if (!isDeletion && !isModifier && !isArrowKey && isInvalidCharacter)
|
|
31
|
+
if (!isDeletion && !isModifier && !isArrowKey && isInvalidCharacter && !isTab)
|
|
31
32
|
event.preventDefault();
|
|
32
33
|
};
|
|
33
34
|
let inputTarget;
|
|
@@ -38,28 +39,31 @@ const currencySymbol = formatCurrency(0, 0)
|
|
|
38
39
|
.replace(/\u00A0/, ''); // e.g '0 €' > '€'
|
|
39
40
|
// Updates `value` by stripping away the currency formatting
|
|
40
41
|
const setUnformattedValue = (event) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
42
|
+
if (event) {
|
|
43
|
+
// Don't format if the user is typing a `currencyDecimal` point
|
|
44
|
+
if (event.key === currencyDecimal)
|
|
45
|
+
return;
|
|
46
|
+
// Pressing `.` when the decimal point is `,` gets replaced with `,`
|
|
47
|
+
if (isDecimalComma && event.key === '.')
|
|
48
|
+
formattedValue = formattedValue.replace(/\.([^.]*)$/, currencyDecimal + '$1'); // Only replace the last occurence
|
|
49
|
+
// Pressing `,` when the decimal point is `.` gets replaced with `.`
|
|
50
|
+
if (!isDecimalComma && event.key === ',')
|
|
51
|
+
formattedValue = formattedValue.replace(/\,([^,]*)$/, currencyDecimal + '$1'); // Only replace the last occurence
|
|
52
|
+
// Don't format if `formattedValue` is ['$', '-$', "-"]
|
|
53
|
+
const ignoreSymbols = [currencySymbol, `-${currencySymbol}`, '-'];
|
|
54
|
+
const strippedUnformattedValue = formattedValue.replace(' ', '');
|
|
55
|
+
if (ignoreSymbols.includes(strippedUnformattedValue))
|
|
56
|
+
return;
|
|
57
|
+
// Set the starting caret positions
|
|
58
|
+
inputTarget = event.target;
|
|
59
|
+
// Reverse the value when minus is pressed
|
|
60
|
+
if (isNegativeAllowed && event.key === '-')
|
|
61
|
+
value = value * -1;
|
|
62
|
+
}
|
|
56
63
|
// Remove all characters that arent: numbers, commas, periods (or minus signs if `isNegativeAllowed`)
|
|
57
64
|
let unformattedValue = isNegativeAllowed
|
|
58
65
|
? formattedValue.replace(/[^0-9,.-]/g, '')
|
|
59
66
|
: formattedValue.replace(/[^0-9,.]/g, '');
|
|
60
|
-
// Reverse the value when minus is pressed
|
|
61
|
-
if (isNegativeAllowed && event.key === '-')
|
|
62
|
-
value = value * -1;
|
|
63
67
|
// Finally set the value
|
|
64
68
|
if (Number.isNaN(parseFloat(unformattedValue))) {
|
|
65
69
|
value = 0;
|
|
@@ -69,7 +73,18 @@ const setUnformattedValue = (event) => {
|
|
|
69
73
|
unformattedValue = unformattedValue.replace(isDecimalComma ? /\./g : /\,/g, ''); // Remove all group symbols
|
|
70
74
|
if (isDecimalComma)
|
|
71
75
|
unformattedValue = unformattedValue.replace(',', '.'); // If the decimal point is a comma, replace it with a period
|
|
76
|
+
// If the zero-key has been pressed
|
|
77
|
+
// and if the current `value` is the same as the `value` before the key-press
|
|
78
|
+
// formatting may need to be done (Issue #30)
|
|
79
|
+
const previousValue = value;
|
|
72
80
|
value = parseFloat(unformattedValue);
|
|
81
|
+
if (event && previousValue === value) {
|
|
82
|
+
// Do the formatting if the number of digits after the decimal point exceeds `fractionDigits`
|
|
83
|
+
if (unformattedValue.includes('.') &&
|
|
84
|
+
unformattedValue.split('.')[1].length > fractionDigits) {
|
|
85
|
+
setFormattedValue();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
89
|
};
|
|
75
90
|
const setFormattedValue = () => {
|
|
@@ -78,6 +93,8 @@ const setFormattedValue = () => {
|
|
|
78
93
|
const previousFormattedValueLength = formattedValue.length;
|
|
79
94
|
// Apply formatting to input
|
|
80
95
|
formattedValue = isZero ? '' : formatCurrency(value, fractionDigits, 0);
|
|
96
|
+
// Update `value` after formatting
|
|
97
|
+
setUnformattedValue();
|
|
81
98
|
// New caret position
|
|
82
99
|
const endCaretPosition = startCaretPosition + formattedValue.length - previousFormattedValueLength;
|
|
83
100
|
// HACK:
|
|
@@ -111,6 +128,7 @@ $: value, setFormattedValue();
|
|
|
111
128
|
bind:value={formattedValue}
|
|
112
129
|
on:keydown={handleKeyDown}
|
|
113
130
|
on:keyup={setUnformattedValue}
|
|
131
|
+
on:blur={setFormattedValue}
|
|
114
132
|
/>
|
|
115
133
|
</div>
|
|
116
134
|
|
package/README.md
CHANGED
|
@@ -118,3 +118,20 @@ npm run dev
|
|
|
118
118
|
# or start the server and open the app in a new browser tab
|
|
119
119
|
npm run dev -- --open
|
|
120
120
|
```
|
|
121
|
+
|
|
122
|
+
#### Integration tests
|
|
123
|
+
|
|
124
|
+
The component is tested using [Playwright](https://playwright.dev/).
|
|
125
|
+
You can find the tests in [`tests/svelte-currency-input.test.ts`](https://github.com/Canutin/svelte-currency-input/blob/main/tests/svelte-currency-input.test.ts)
|
|
126
|
+
|
|
127
|
+
To run all tests on **Chromium**, **Firefox** and **Webkit**:
|
|
128
|
+
```bash
|
|
129
|
+
npm run test
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
To run all tests on a specific browser (e.g. **Webkit**):
|
|
133
|
+
```bash
|
|
134
|
+
npx playwright test --project=webkit
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Additional debug commands can be found on [Playwright's documentation](https://playwright.dev/docs/test-cli).
|