@momo-kits/foundation 0.168.1-beta.6 → 0.168.1-beta.8
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/Input/InputMoney.tsx +42 -53
- package/Input/styles.ts +9 -0
- package/package.json +1 -1
package/Input/InputMoney.tsx
CHANGED
|
@@ -9,6 +9,8 @@ import React, {
|
|
|
9
9
|
} from 'react';
|
|
10
10
|
import {
|
|
11
11
|
Platform,
|
|
12
|
+
Pressable,
|
|
13
|
+
Text,
|
|
12
14
|
TextInput,
|
|
13
15
|
TextInputFocusEvent,
|
|
14
16
|
TouchableOpacity,
|
|
@@ -22,7 +24,6 @@ import {
|
|
|
22
24
|
} from '../Context';
|
|
23
25
|
import { Icon } from '../Icon';
|
|
24
26
|
import { useScaleSize, exportFontFamily } from '../Text';
|
|
25
|
-
import { Spacing } from '../Consts';
|
|
26
27
|
import {
|
|
27
28
|
ErrorView,
|
|
28
29
|
FloatingView,
|
|
@@ -32,11 +33,10 @@ import {
|
|
|
32
33
|
} from './common';
|
|
33
34
|
import { InputMoneyProps } from './index';
|
|
34
35
|
import styles from './styles';
|
|
35
|
-
import { formatNumberToMoney } from './utils';
|
|
36
36
|
import SystemTextInput from './SystemTextInput';
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const moneyFormatter = new Intl.NumberFormat('vi-VN');
|
|
39
|
+
|
|
40
40
|
const findEdit = (old: string, text: string) => {
|
|
41
41
|
let start = 0;
|
|
42
42
|
while (start < text.length && old[start] === text[start]) {
|
|
@@ -127,24 +127,17 @@ const InputMoney = forwardRef(
|
|
|
127
127
|
setLastDisplayValue(displayValue);
|
|
128
128
|
}, [displayValue]);
|
|
129
129
|
|
|
130
|
-
// The selection only rides along with the render that reformats the text,
|
|
131
|
-
// then it is released so the user can move the caret freely.
|
|
132
130
|
useEffect(() => {
|
|
133
131
|
if (!caretSelection) return;
|
|
134
|
-
// A newer keystroke may already have queued its own selection; keep it.
|
|
135
132
|
setCaretSelection(current =>
|
|
136
133
|
current === caretSelection ? undefined : current,
|
|
137
134
|
);
|
|
138
135
|
}, [caretSelection]);
|
|
139
136
|
|
|
140
137
|
const updateDisplayValue = (numeric: string) => {
|
|
141
|
-
const
|
|
142
|
-
const next = formatted ? `${formatted}${currency}` : '';
|
|
138
|
+
const next = numeric ? moneyFormatter.format(Number(numeric)) : '';
|
|
143
139
|
setDisplayValue(next);
|
|
144
140
|
|
|
145
|
-
// Android moves the caret proportionally when the text is replaced, so
|
|
146
|
-
// it lands before the typed digit once a separator is added. Send the
|
|
147
|
-
// caret together with the text so a fast keystroke can't land in between.
|
|
148
141
|
const digitsAfter = caretDigitsAfter.current;
|
|
149
142
|
caretDigitsAfter.current = undefined;
|
|
150
143
|
if (Platform.OS !== 'android' || digitsAfter === undefined) return;
|
|
@@ -157,12 +150,7 @@ const InputMoney = forwardRef(
|
|
|
157
150
|
setCaretSelection({ start: caret, end: caret });
|
|
158
151
|
};
|
|
159
152
|
|
|
160
|
-
const parseInputText = (text: string): string =>
|
|
161
|
-
if (!text) return '';
|
|
162
|
-
const currencyRegex = new RegExp(` ?${currency}$`, 'g');
|
|
163
|
-
const textWithoutCurrency = text.replace(currencyRegex, '').trim();
|
|
164
|
-
return textWithoutCurrency.replace(/[^\d]/g, '');
|
|
165
|
-
};
|
|
153
|
+
const parseInputText = (text: string): string => text.replace(/\D/g, '');
|
|
166
154
|
|
|
167
155
|
const updateNumericValue = (val: string) => {
|
|
168
156
|
let next = val.replace(/[^\d]/g, '').replace(/^0+(?=\d)/, '');
|
|
@@ -190,34 +178,24 @@ const InputMoney = forwardRef(
|
|
|
190
178
|
onChangeText?.('');
|
|
191
179
|
return;
|
|
192
180
|
}
|
|
193
|
-
|
|
194
|
-
// formatted text and keeps the raw one, so the edit may apply to either.
|
|
195
|
-
// Pick the one that differs from the new text by a single edit.
|
|
181
|
+
const digits = parseInputText(text);
|
|
196
182
|
const raw = lastRawText.current;
|
|
197
183
|
lastRawText.current = text;
|
|
198
184
|
const formattedEdit = findEdit(lastDisplayValue, text);
|
|
199
185
|
const rawEdit = findEdit(raw, text);
|
|
200
186
|
const { old, start, suffix } =
|
|
201
187
|
raw && rawEdit.size < formattedEdit.size ? rawEdit : formattedEdit;
|
|
202
|
-
caretDigitsAfter.current =
|
|
203
|
-
.slice(text.length - suffix)
|
|
204
|
-
|
|
205
|
-
if (text.length < old.length) {
|
|
206
|
-
const
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
? parseInputText(old.slice(0, start)).length - 1
|
|
210
|
-
: numericValue.length - 1;
|
|
211
|
-
if (index >= 0) {
|
|
212
|
-
updateNumericValue(
|
|
213
|
-
numericValue.slice(0, index) + numericValue.slice(index + 1),
|
|
214
|
-
);
|
|
215
|
-
}
|
|
188
|
+
caretDigitsAfter.current = parseInputText(
|
|
189
|
+
text.slice(text.length - suffix),
|
|
190
|
+
).length;
|
|
191
|
+
if (text.length < old.length && digits === numericValue) {
|
|
192
|
+
const index = parseInputText(text.slice(0, start)).length - 1;
|
|
193
|
+
if (index >= 0) {
|
|
194
|
+
updateNumericValue(digits.slice(0, index) + digits.slice(index + 1));
|
|
216
195
|
return;
|
|
217
196
|
}
|
|
218
197
|
}
|
|
219
|
-
|
|
220
|
-
updateNumericValue(newNumericValue);
|
|
198
|
+
updateNumericValue(digits);
|
|
221
199
|
};
|
|
222
200
|
|
|
223
201
|
const _onFocus = (e: TextInputFocusEvent) => {
|
|
@@ -261,6 +239,14 @@ const InputMoney = forwardRef(
|
|
|
261
239
|
placeholderColor = disabledColor;
|
|
262
240
|
iconTintColor = disabledColor;
|
|
263
241
|
}
|
|
242
|
+
const textStyle = {
|
|
243
|
+
fontSize: scaledFontSize,
|
|
244
|
+
fontFamily: inputFontFamily,
|
|
245
|
+
};
|
|
246
|
+
const placeholderHasCurrency = placeholder.endsWith(currency);
|
|
247
|
+
const inputPlaceholder = placeholderHasCurrency
|
|
248
|
+
? placeholder.slice(0, -currency.length)
|
|
249
|
+
: placeholder;
|
|
264
250
|
return (
|
|
265
251
|
<View
|
|
266
252
|
style={[
|
|
@@ -279,7 +265,11 @@ const InputMoney = forwardRef(
|
|
|
279
265
|
onPress={onPressFloatingIcon}
|
|
280
266
|
componentId={componentId}
|
|
281
267
|
/>
|
|
282
|
-
<
|
|
268
|
+
<Pressable
|
|
269
|
+
style={[styles.inputView, styles.moneyInputView]}
|
|
270
|
+
onPress={() => inputRef.current?.focus()}
|
|
271
|
+
disabled={disabled}
|
|
272
|
+
>
|
|
283
273
|
<SystemTextInput
|
|
284
274
|
{...props}
|
|
285
275
|
accessibilityLabel={`${componentId}`}
|
|
@@ -289,19 +279,7 @@ const InputMoney = forwardRef(
|
|
|
289
279
|
disabled: disabled,
|
|
290
280
|
...props.accessibilityState,
|
|
291
281
|
}}
|
|
292
|
-
style={[
|
|
293
|
-
{
|
|
294
|
-
width: '100%',
|
|
295
|
-
paddingLeft: Spacing.M,
|
|
296
|
-
height: '100%',
|
|
297
|
-
fontSize: scaledFontSize,
|
|
298
|
-
paddingVertical: Spacing.S,
|
|
299
|
-
fontFamily: inputFontFamily,
|
|
300
|
-
},
|
|
301
|
-
{
|
|
302
|
-
color: textColor,
|
|
303
|
-
},
|
|
304
|
-
]}
|
|
282
|
+
style={[textStyle, styles.moneyTextInput, { color: textColor }]}
|
|
305
283
|
allowFontScaling={false}
|
|
306
284
|
textBreakStrategy="highQuality"
|
|
307
285
|
value={displayValue}
|
|
@@ -309,13 +287,24 @@ const InputMoney = forwardRef(
|
|
|
309
287
|
onChangeText={_onChangeText}
|
|
310
288
|
onFocus={_onFocus}
|
|
311
289
|
onBlur={_onBlur}
|
|
312
|
-
placeholder={
|
|
290
|
+
placeholder={inputPlaceholder}
|
|
313
291
|
selectionColor={theme.colors.primary}
|
|
314
292
|
placeholderTextColor={placeholderColor}
|
|
315
293
|
keyboardType={'numeric'}
|
|
316
294
|
maxLength={undefined}
|
|
317
295
|
/>
|
|
318
|
-
|
|
296
|
+
{displayValue || placeholderHasCurrency ? (
|
|
297
|
+
<Text
|
|
298
|
+
style={[
|
|
299
|
+
textStyle,
|
|
300
|
+
{ color: displayValue ? textColor : placeholderColor },
|
|
301
|
+
]}
|
|
302
|
+
allowFontScaling={false}
|
|
303
|
+
>
|
|
304
|
+
{currency}
|
|
305
|
+
</Text>
|
|
306
|
+
) : null}
|
|
307
|
+
</Pressable>
|
|
319
308
|
<View style={styles.iconView}>
|
|
320
309
|
{showClearIcon && focused && displayValue ? (
|
|
321
310
|
<TouchableOpacity
|
package/Input/styles.ts
CHANGED
|
@@ -218,4 +218,13 @@ export default StyleSheet.create({
|
|
|
218
218
|
marginLeft: Spacing.M,
|
|
219
219
|
},
|
|
220
220
|
debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
|
|
221
|
+
moneyInputView: {
|
|
222
|
+
paddingLeft: Spacing.M,
|
|
223
|
+
},
|
|
224
|
+
moneyTextInput: {
|
|
225
|
+
flexShrink: 1,
|
|
226
|
+
paddingLeft: 0,
|
|
227
|
+
paddingRight: Spacing.XXS,
|
|
228
|
+
paddingVertical: 0,
|
|
229
|
+
},
|
|
221
230
|
});
|