@veritree/ui 0.81.0 → 0.82.0-1
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/mixins/form-control.js
CHANGED
|
@@ -73,7 +73,7 @@ export const formControlStyleMixin = {
|
|
|
73
73
|
return [
|
|
74
74
|
this.headless
|
|
75
75
|
? `${this.name}`
|
|
76
|
-
: 'leading-0 bg-white disabled:bg-gray-200 flex w-full max-w-full relative appearance-none placeholder:font-light placeholder:text-gray-500 items-center justify-between rounded border border-solid px-3 py-2 font-inherit text-inherit file:hidden focus:border-gray-600 focus:placeholder:text-gray-400 disabled:text-gray-500',
|
|
76
|
+
: 'leading-0 bg-white has-[:disabled]:bg-gray-200 disabled:bg-gray-200 flex w-full max-w-full relative appearance-none placeholder:font-light placeholder:text-gray-500 items-center justify-between rounded border border-solid px-3 py-2 font-inherit text-inherit file:hidden focus-within:border-gray-600 focus:border-gray-600 focus-within:placeholder:text-gray-400 focus:placeholder:text-gray-400 has-[:disabled]:text-gray-500 disabled:text-gray-500',
|
|
77
77
|
// variant styles
|
|
78
78
|
this.headless
|
|
79
79
|
? `${this.name}--${this.variant}`
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
v-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
<div :class="inputNumberClassComputed">
|
|
3
|
+
<span v-if="format === 'currency'" class="grow-0 mr-1">{{
|
|
4
|
+
currencySymbol
|
|
5
|
+
}}</span>
|
|
6
|
+
<input
|
|
7
|
+
v-model="valueFormatted"
|
|
8
|
+
:disabled="disabled"
|
|
9
|
+
class="w-full"
|
|
10
|
+
@input="onInput"
|
|
11
|
+
@change="onChange"
|
|
12
|
+
@blur="onBlur"
|
|
13
|
+
@keydown="onKeyDown"
|
|
14
|
+
/>
|
|
15
|
+
</div>
|
|
10
16
|
</template>
|
|
11
17
|
|
|
12
18
|
<script>
|
|
@@ -14,6 +20,7 @@ import {
|
|
|
14
20
|
formControlMixin,
|
|
15
21
|
formControlStyleMixin,
|
|
16
22
|
} from '../../../mixins/form-control';
|
|
23
|
+
import { getCurrencySymbol } from '../../helpers/currency';
|
|
17
24
|
|
|
18
25
|
export default {
|
|
19
26
|
name: 'VTInputNumber',
|
|
@@ -26,12 +33,32 @@ export default {
|
|
|
26
33
|
},
|
|
27
34
|
|
|
28
35
|
props: {
|
|
36
|
+
currency: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: 'USD',
|
|
39
|
+
},
|
|
40
|
+
locale: {
|
|
41
|
+
type: String,
|
|
42
|
+
default: 'en-US',
|
|
43
|
+
},
|
|
44
|
+
// different type of number input (e.g. 'integer', 'decimal', 'currency')
|
|
45
|
+
format: {
|
|
46
|
+
type: String,
|
|
47
|
+
default: 'integer',
|
|
48
|
+
},
|
|
29
49
|
value: {
|
|
30
50
|
type: [String, Number, Object, Array, Date],
|
|
31
51
|
default: null,
|
|
32
52
|
},
|
|
33
53
|
},
|
|
34
54
|
|
|
55
|
+
data() {
|
|
56
|
+
return {
|
|
57
|
+
event: 'input',
|
|
58
|
+
key: null,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
|
|
35
62
|
computed: {
|
|
36
63
|
valueComputed: {
|
|
37
64
|
get() {
|
|
@@ -48,12 +75,44 @@ export default {
|
|
|
48
75
|
|
|
49
76
|
valueFormatted: {
|
|
50
77
|
get() {
|
|
51
|
-
|
|
78
|
+
if (this.value === 0 && this.event === 'blur') {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let options = {};
|
|
83
|
+
|
|
84
|
+
// only add the fraction digits on blur because on input it won't behave nicely
|
|
85
|
+
if (this.format === 'currency' && this.event === 'blur') {
|
|
86
|
+
options = {
|
|
87
|
+
minimumFractionDigits: 2,
|
|
88
|
+
maximumFractionDigits: 2,
|
|
89
|
+
};
|
|
90
|
+
} else {
|
|
91
|
+
options = {};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return Number(this.value).toLocaleString(this.locale, options);
|
|
52
95
|
},
|
|
53
96
|
set(value) {
|
|
97
|
+
// value without formatting that will be
|
|
54
98
|
this.valueComputed = value;
|
|
55
99
|
},
|
|
56
100
|
},
|
|
101
|
+
|
|
102
|
+
currencySymbol() {
|
|
103
|
+
return getCurrencySymbol({
|
|
104
|
+
locale: this.locale,
|
|
105
|
+
currency: this.currency,
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
inputNumberClassComputed() {
|
|
110
|
+
if (this.format === 'currency') {
|
|
111
|
+
return [this.classComputed, 'flex justify-start'];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return this.classComputed;
|
|
115
|
+
},
|
|
57
116
|
},
|
|
58
117
|
|
|
59
118
|
methods: {
|
|
@@ -68,6 +127,10 @@ export default {
|
|
|
68
127
|
return null; // or any other appropriate value or behavior
|
|
69
128
|
}
|
|
70
129
|
|
|
130
|
+
if (this.format === 'currency') {
|
|
131
|
+
return parseFloat(number.replace(/,/g, ''));
|
|
132
|
+
}
|
|
133
|
+
|
|
71
134
|
return parseInt(number.replace(/,/g, ''), 10);
|
|
72
135
|
},
|
|
73
136
|
|
|
@@ -91,12 +154,42 @@ export default {
|
|
|
91
154
|
},
|
|
92
155
|
|
|
93
156
|
onInput(e) {
|
|
157
|
+
this.event = 'input';
|
|
94
158
|
this.valueComputed = e.target.value;
|
|
95
159
|
},
|
|
96
160
|
|
|
97
|
-
onBlur() {
|
|
161
|
+
onBlur(e) {
|
|
162
|
+
this.event = 'blur';
|
|
163
|
+
|
|
164
|
+
// only set valueComputed if it's greater than 0
|
|
165
|
+
if (!this.valueComputed && this.valueComputed > 0) {
|
|
166
|
+
this.valueComputed = e.target.value;
|
|
167
|
+
}
|
|
168
|
+
|
|
98
169
|
this.$emit('blur');
|
|
99
170
|
},
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Handles the keydown event to restrict input to valid characters.
|
|
174
|
+
*
|
|
175
|
+
* This function prevents the default action for any key presses that do not correspond
|
|
176
|
+
* to a digit (0-9), a comma, or a period. It also allows common navigation and editing
|
|
177
|
+
* keys such as Backspace, Delete, Arrow keys, and Tab.
|
|
178
|
+
*
|
|
179
|
+
* @param {Event} e - The keydown event object.
|
|
180
|
+
*/
|
|
181
|
+
onKeyDown(e) {
|
|
182
|
+
if (
|
|
183
|
+
!/^[0-9.,]$/.test(e.key) &&
|
|
184
|
+
!['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab'].includes(
|
|
185
|
+
e.key,
|
|
186
|
+
)
|
|
187
|
+
) {
|
|
188
|
+
e.preventDefault();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
this.key = e.key;
|
|
192
|
+
},
|
|
100
193
|
},
|
|
101
194
|
};
|
|
102
195
|
</script>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const currencyFormatter = ({ locale = 'en-US', currency = 'USD' }) => {
|
|
2
|
+
return Intl.NumberFormat(locale, {
|
|
3
|
+
style: 'currency',
|
|
4
|
+
currency,
|
|
5
|
+
});
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const getCurrencySymbol = (options) => {
|
|
9
|
+
const formatter = currencyFormatter(options);
|
|
10
|
+
const parts = formatter.formatToParts(0); // can be any number
|
|
11
|
+
const currency = parts.find((part) => part.type === 'currency');
|
|
12
|
+
const symbol = currency.value;
|
|
13
|
+
|
|
14
|
+
return removeLetters(symbol);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Remove all letters (for example, change CA$ to $)
|
|
18
|
+
const removeLetters = (value) => {
|
|
19
|
+
const lettersRegex = /[A-Za-z]/g;
|
|
20
|
+
return value.replaceAll(lettersRegex, '');
|
|
21
|
+
};
|