@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.
@@ -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
- // Finds the common prefix and suffix of `old` and `text`; `size` counts the
39
- // characters removed plus inserted between them.
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 formatted = numeric ? formatNumberToMoney(Number(numeric)) : '';
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
- // When typing outpaces JS (slow Android devices) native rejects the stale
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 = text
203
- .slice(text.length - suffix)
204
- .replace(/\D/g, '').length;
205
- if (text.length < old.length) {
206
- const removed = old.slice(start, old.length - suffix);
207
- if (!/\d/.test(removed)) {
208
- const index = removed.includes('.')
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
- const newNumericValue = parseInputText(text);
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
- <View style={styles.inputView}>
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={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
- </View>
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.168.1-beta.6",
3
+ "version": "0.168.1-beta.8",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},