@momo-kits/foundation 0.167.1-beta.12 → 0.167.1-beta.14

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.
Files changed (54) hide show
  1. package/Application/BottomSheet.tsx +246 -42
  2. package/Application/BottomTab/BottomTabBar.tsx +6 -3
  3. package/Application/BottomTab/CustomBottomTabItem.tsx +3 -5
  4. package/Application/BottomTab/DuoBarCompression.tsx +135 -0
  5. package/Application/BottomTab/DuoTabBar.tsx +537 -0
  6. package/Application/BottomTab/index.tsx +145 -134
  7. package/Application/Components/DuoGlassBackground.tsx +158 -0
  8. package/Application/Components/DuoQuickReturnHeader.tsx +42 -0
  9. package/Application/Components/HeaderAnimated.tsx +9 -3
  10. package/Application/Components/HeaderExtendHeader.tsx +70 -28
  11. package/Application/Components/HeaderLeft.tsx +38 -0
  12. package/Application/Components/HeaderRight.tsx +144 -9
  13. package/Application/Components/HeaderTitle.tsx +43 -7
  14. package/Application/Components/SearchHeader.tsx +20 -15
  15. package/Application/Components/SideBarButton.tsx +134 -0
  16. package/Application/ModalScreen.tsx +20 -2
  17. package/Application/NavigationContainer.tsx +22 -38
  18. package/Application/Navigator.ts +1 -3
  19. package/Application/StackScreen.tsx +2 -5
  20. package/Application/device.ts +52 -0
  21. package/Application/types.ts +10 -1
  22. package/Application/utils.tsx +10 -7
  23. package/Badge/Badge.tsx +2 -3
  24. package/Badge/BadgeDotAnimation.tsx +3 -3
  25. package/Button/index.tsx +11 -11
  26. package/Consts/theme.ts +3 -4
  27. package/Input/Input.tsx +3 -4
  28. package/Input/InputMoney.tsx +123 -194
  29. package/Input/InputOTP.tsx +9 -12
  30. package/Input/InputPhoneNumber.tsx +3 -4
  31. package/Input/InputSearch.tsx +17 -14
  32. package/Input/InputTextArea.tsx +3 -4
  33. package/Input/SystemTextInput.tsx +2 -3
  34. package/Input/TextTyping.tsx +11 -6
  35. package/Input/styles.ts +9 -0
  36. package/Input/utils.ts +2 -3
  37. package/Layout/Card.tsx +8 -26
  38. package/Layout/FloatingButton.tsx +3 -3
  39. package/Layout/Item.tsx +1 -10
  40. package/Layout/ReservedRegions.tsx +78 -0
  41. package/Layout/Screen.tsx +242 -48
  42. package/Layout/Section.tsx +5 -18
  43. package/Layout/index.ts +4 -4
  44. package/Layout/styles.ts +5 -0
  45. package/Layout/utils.ts +478 -5
  46. package/Pagination/Dot.tsx +3 -6
  47. package/Popup/PopupNotify.tsx +49 -28
  48. package/Popup/PopupPromotion.tsx +21 -8
  49. package/Popup/utils.ts +26 -0
  50. package/Radio/index.tsx +2 -3
  51. package/Text/utils.ts +2 -3
  52. package/Title/index.tsx +8 -11
  53. package/package.json +5 -2
  54. package/Layout/GridSystem.tsx +0 -137
@@ -4,15 +4,15 @@ import React, {
4
4
  useContext,
5
5
  useEffect,
6
6
  useImperativeHandle,
7
- useLayoutEffect,
8
7
  useRef,
9
8
  useState,
10
9
  } from 'react';
11
10
  import {
12
- NativeSyntheticEvent,
11
+ Platform,
12
+ Pressable,
13
+ Text,
13
14
  TextInput,
14
- TextInputFocusEventData,
15
- TextInputSelectionChangeEventData,
15
+ TextInputFocusEvent,
16
16
  TouchableOpacity,
17
17
  View,
18
18
  } from 'react-native';
@@ -24,7 +24,6 @@ import {
24
24
  } from '../Context';
25
25
  import { Icon } from '../Icon';
26
26
  import { useScaleSize, exportFontFamily } from '../Text';
27
- import { Spacing } from '../Consts';
28
27
  import {
29
28
  ErrorView,
30
29
  FloatingView,
@@ -36,97 +35,22 @@ import { InputMoneyProps } from './index';
36
35
  import styles from './styles';
37
36
  import SystemTextInput from './SystemTextInput';
38
37
 
39
- type Selection = { start: number; end: number };
40
- type Edit = { start: number; end: number; inserted: string };
38
+ const moneyFormatter = new Intl.NumberFormat('vi-VN');
41
39
 
42
- const countDigits = (text: string) => text.replace(/\D/g, '').length;
43
-
44
- const groupDigits = (digits: string) =>
45
- digits.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
46
-
47
- // Caret position right after the `digitIndex`-th digit of `display`.
48
- const caretFromDigitIndex = (display: string, digitIndex: number) => {
49
- let count = 0;
50
- for (let i = 0; i < display.length && count < digitIndex; i++) {
51
- if (/\d/.test(display[i])) {
52
- count += 1;
53
- if (count === digitIndex) return i + 1;
54
- }
55
- }
56
- return 0;
57
- };
58
-
59
- const detectEdit = (old: string, next: string, selection: Selection): Edit => {
60
- const { start, end } = selection;
61
- const removed = old.length - next.length;
62
- const candidates: Edit[] = [
63
- {
64
- start,
65
- end,
66
- inserted: next.slice(start, next.length - (old.length - end)),
67
- },
68
- { start: start - removed, end: start, inserted: '' },
69
- { start, end: start + removed, inserted: '' },
70
- ];
71
- const match = candidates.find(
72
- e =>
73
- e.start >= 0 &&
74
- e.end >= e.start &&
75
- e.end <= old.length &&
76
- old.slice(0, e.start) + e.inserted + old.slice(e.end) === next,
77
- );
78
- if (match) return match;
79
-
80
- let prefix = 0;
81
- while (
82
- prefix < Math.min(old.length, next.length) &&
83
- old[prefix] === next[prefix]
84
- ) {
85
- prefix += 1;
40
+ const findEdit = (old: string, text: string) => {
41
+ let start = 0;
42
+ while (start < text.length && old[start] === text[start]) {
43
+ start += 1;
86
44
  }
87
45
  let suffix = 0;
88
46
  while (
89
- suffix < Math.min(old.length, next.length) - prefix &&
90
- old[old.length - 1 - suffix] === next[next.length - 1 - suffix]
47
+ suffix < Math.min(text.length, old.length) - start &&
48
+ old[old.length - 1 - suffix] === text[text.length - 1 - suffix]
91
49
  ) {
92
50
  suffix += 1;
93
51
  }
94
- return {
95
- start: prefix,
96
- end: old.length - suffix,
97
- inserted: next.slice(prefix, next.length - suffix),
98
- };
99
- };
100
-
101
- // Applies `edit` to the digits of `display`. Separators and currency are never
102
- // deleted: removing a separator deletes the digit before it instead, removing
103
- // only the currency leaves the digits untouched.
104
- const applyEdit = (display: string, edit: Edit, digitLimit: number) => {
105
- const digits = display.replace(/\D/g, '');
106
- let left = countDigits(display.slice(0, edit.start));
107
- let removed = countDigits(display.slice(edit.start, edit.end));
108
- const inserted = edit.inserted.replace(/\D/g, '');
109
- if (
110
- !removed &&
111
- !inserted &&
112
- left > 0 &&
113
- display.slice(edit.start, edit.end).includes('.')
114
- ) {
115
- left -= 1;
116
- removed = 1;
117
- }
118
- const next = digits.slice(0, left) + inserted + digits.slice(left + removed);
119
- const trimmed = next.replace(/^0+(?=\d)/, '');
120
- if ((!removed && !inserted) || trimmed.length > digitLimit) {
121
- return { digits, caretDigit: left };
122
- }
123
- return {
124
- digits: trimmed,
125
- caretDigit: Math.max(
126
- 0,
127
- left + inserted.length - (next.length - trimmed.length),
128
- ),
129
- };
52
+ const size = old.length + text.length - 2 * (start + suffix);
53
+ return { old, start, suffix, size };
130
54
  };
131
55
 
132
56
  const InputMoney = forwardRef(
@@ -167,14 +91,14 @@ const InputMoney = forwardRef(
167
91
  const [focused, setFocused] = useState(false);
168
92
  const [displayValue, setDisplayValue] = useState('');
169
93
  const [numericValue, setNumericValue] = useState('');
170
- const [commitCount, setCommitCount] = useState(0);
171
- const displayRef = useRef('');
172
- const selectionRef = useRef<Selection>({ start: 0, end: 0 });
173
- // Caret to push to native once the committed text is rendered.
174
- const pendingCaretRef = useRef<number | null>(null);
175
- const pendingSelectionRef = useRef<Selection | null>(null);
176
- const editingRef = useRef(false);
94
+ const [lastDisplayValue, setLastDisplayValue] = useState('');
177
95
  const inputRef = useRef<TextInput>(null);
96
+ const caretDigitsAfter = useRef<number | undefined>(undefined);
97
+ const lastRawText = useRef('');
98
+ const [caretSelection, setCaretSelection] = useState<{
99
+ start: number;
100
+ end: number;
101
+ }>();
178
102
  const componentName = 'InputMoney';
179
103
 
180
104
  const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
@@ -184,127 +108,121 @@ const InputMoney = forwardRef(
184
108
  props.accessibilityLabel,
185
109
  );
186
110
 
187
- const digitLimit =
188
- typeof (props as any)?.maxLength === 'number'
189
- ? (props as any).maxLength
190
- : Number.POSITIVE_INFINITY;
111
+ const maxLength = (props as any)?.maxLength;
112
+ const hasMaxLength = typeof maxLength === 'number';
113
+ const digitLimit = hasMaxLength ? maxLength : Number.POSITIVE_INFINITY;
191
114
 
192
115
  useEffect(() => {
193
116
  if (value !== undefined && typeof value === 'string') {
194
117
  const cleanValue = value.replace(/\D/g, '').replace(/^0+(?=\d)/, '');
195
118
  if (cleanValue !== numericValue) {
196
- commit(cleanValue, cleanValue.length);
119
+ caretDigitsAfter.current = undefined;
120
+ setNumericValue(cleanValue);
121
+ updateDisplayValue(cleanValue);
197
122
  }
198
123
  }
199
124
  }, [value]);
200
125
 
201
- // Always set the caret imperatively: a controlled `selection` prop is only
202
- // sent to native when it differs from the last native selection, so it is
203
- // skipped whenever a stale selection event already reported the same value.
204
- useLayoutEffect(() => {
205
- const caret = pendingCaretRef.current;
206
- if (caret === null) return;
207
- pendingCaretRef.current = null;
208
- if (inputRef.current?.isFocused()) {
209
- inputRef.current.setSelection(caret, caret);
210
- }
211
- }, [commitCount]);
126
+ useEffect(() => {
127
+ setLastDisplayValue(displayValue);
128
+ }, [displayValue]);
212
129
 
213
- const commit = (digits: string, caretDigit: number) => {
214
- const display = digits ? `${groupDigits(digits)}${currency}` : '';
215
- const caret = caretFromDigitIndex(display, caretDigit);
216
- const changed = digits !== numericValue;
217
- displayRef.current = display;
218
- selectionRef.current = { start: caret, end: caret };
219
- pendingCaretRef.current = caret;
220
- setCommitCount(count => count + 1);
221
- setDisplayValue(display);
222
- setNumericValue(digits);
223
- return changed;
130
+ useEffect(() => {
131
+ if (!caretSelection) return;
132
+ setCaretSelection(current =>
133
+ current === caretSelection ? undefined : current,
134
+ );
135
+ }, [caretSelection]);
136
+
137
+ const updateDisplayValue = (numeric: string) => {
138
+ const next = numeric ? moneyFormatter.format(Number(numeric)) : '';
139
+ setDisplayValue(next);
140
+
141
+ const digitsAfter = caretDigitsAfter.current;
142
+ caretDigitsAfter.current = undefined;
143
+ if (Platform.OS !== 'android' || digitsAfter === undefined) return;
144
+ let before = parseInputText(next).length - digitsAfter;
145
+ let caret = 0;
146
+ while (before > 0 && caret < next.length) {
147
+ if (/\d/.test(next[caret])) before -= 1;
148
+ caret += 1;
149
+ }
150
+ setCaretSelection({ start: caret, end: caret });
224
151
  };
225
152
 
226
- const parseInputText = (text: string): string => {
227
- if (!text) return '';
228
- const currencyRegex = new RegExp(` ?${currency}$`, 'g');
229
- const textWithoutCurrency = text.replace(currencyRegex, '').trim();
230
- return textWithoutCurrency.replace(/[^\d]/g, '');
153
+ const parseInputText = (text: string): string => text.replace(/\D/g, '');
154
+
155
+ const updateNumericValue = (val: string) => {
156
+ let next = val.replace(/[^\d]/g, '').replace(/^0+(?=\d)/, '');
157
+ if (next.length > digitLimit) next = next.slice(0, digitLimit);
158
+ if (/^\d*$/.test(next)) {
159
+ setNumericValue(next);
160
+ updateDisplayValue(next);
161
+ onChangeText?.(next);
162
+ }
231
163
  };
232
164
 
233
165
  const onClearText = () => {
234
166
  inputRef?.current?.clear();
235
167
  inputRef.current?.setNativeProps({ text: '' });
236
- commit('', 0);
168
+ setDisplayValue('');
169
+ setNumericValue('');
237
170
  onChangeText?.('');
238
171
  };
239
172
 
240
173
  const _onChangeText = (text: string) => {
241
- let digits = '';
242
- let caretDigit = 0;
243
- pendingSelectionRef.current = null;
244
- editingRef.current = true;
245
- setTimeout(() => {
246
- editingRef.current = false;
247
- });
248
- if (text) {
249
- const edit = detectEdit(displayRef.current, text, selectionRef.current);
250
- ({ digits, caretDigit } = applyEdit(
251
- displayRef.current,
252
- edit,
253
- digitLimit,
254
- ));
174
+ if (!text) {
175
+ lastRawText.current = '';
176
+ setDisplayValue('');
177
+ setNumericValue('');
178
+ onChangeText?.('');
179
+ return;
255
180
  }
256
- if (commit(digits, caretDigit)) {
257
- onChangeText?.(digits);
181
+ const digits = parseInputText(text);
182
+ const raw = lastRawText.current;
183
+ lastRawText.current = text;
184
+ const formattedEdit = findEdit(lastDisplayValue, text);
185
+ const rawEdit = findEdit(raw, text);
186
+ const { old, start, suffix } =
187
+ raw && rawEdit.size < formattedEdit.size ? rawEdit : formattedEdit;
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));
195
+ return;
196
+ }
258
197
  }
198
+ updateNumericValue(digits);
259
199
  };
260
200
 
261
- // Keeps the caret out of the currency suffix.
262
- const _onSelectionChange = (
263
- e: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
264
- ) => {
265
- props.onSelectionChange?.(e);
266
- if (editingRef.current) return;
267
- const selection = e.nativeEvent.selection;
268
- pendingSelectionRef.current = selection;
269
- setTimeout(() => {
270
- if (pendingSelectionRef.current !== selection) return;
271
- pendingSelectionRef.current = null;
272
- const { start, end } = selection;
273
- const display = displayRef.current;
274
- const max = display ? display.length - currency.length : 0;
275
- const clamped = {
276
- start: Math.min(start, max),
277
- end: Math.min(end, max),
278
- };
279
- selectionRef.current = clamped;
280
- if (clamped.start !== start || clamped.end !== end) {
281
- inputRef.current?.setSelection(clamped.start, clamped.end);
282
- }
283
- });
201
+ const focusAtEnd = () => {
202
+ inputRef.current?.focus();
203
+ inputRef.current?.setSelection(displayValue.length, displayValue.length);
284
204
  };
285
205
 
286
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
206
+ const _onFocus = (e: TextInputFocusEvent) => {
287
207
  setFocused(true);
288
208
  onFocus?.(e);
289
209
  };
290
210
 
291
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
211
+ const _onBlur = (e: TextInputFocusEvent) => {
292
212
  setFocused(false);
293
213
  onBlur?.(e);
294
214
  };
295
215
 
296
216
  const _setText = (text: string) => {
217
+ caretDigitsAfter.current = undefined;
297
218
  if (!text) {
298
- commit('', 0);
219
+ setDisplayValue('');
220
+ setNumericValue('');
299
221
  onChangeText?.('');
300
222
  return;
301
223
  }
302
- const digits = parseInputText(text)
303
- .replace(/^0+(?=\d)/, '')
304
- .slice(0, digitLimit);
305
- if (commit(digits, digits.length)) {
306
- onChangeText?.(digits);
307
- }
224
+ const newNumericValue = parseInputText(text);
225
+ updateNumericValue(newNumericValue);
308
226
  };
309
227
 
310
228
  useImperativeHandle(ref, () => {
@@ -326,6 +244,14 @@ const InputMoney = forwardRef(
326
244
  placeholderColor = disabledColor;
327
245
  iconTintColor = disabledColor;
328
246
  }
247
+ const textStyle = {
248
+ fontSize: scaledFontSize,
249
+ fontFamily: inputFontFamily,
250
+ };
251
+ const placeholderHasCurrency = placeholder.endsWith(currency);
252
+ const inputPlaceholder = placeholderHasCurrency
253
+ ? placeholder.slice(0, -currency.length)
254
+ : placeholder;
329
255
  return (
330
256
  <View
331
257
  style={[
@@ -344,7 +270,11 @@ const InputMoney = forwardRef(
344
270
  onPress={onPressFloatingIcon}
345
271
  componentId={componentId}
346
272
  />
347
- <View style={styles.inputView}>
273
+ <Pressable
274
+ style={[styles.inputView, styles.moneyInputView]}
275
+ onPress={focusAtEnd}
276
+ disabled={disabled}
277
+ >
348
278
  <SystemTextInput
349
279
  {...props}
350
280
  accessibilityLabel={`${componentId}`}
@@ -354,33 +284,32 @@ const InputMoney = forwardRef(
354
284
  disabled: disabled,
355
285
  ...props.accessibilityState,
356
286
  }}
357
- style={[
358
- {
359
- width: '100%',
360
- paddingLeft: Spacing.M,
361
- height: '100%',
362
- fontSize: scaledFontSize,
363
- paddingVertical: Spacing.S,
364
- fontFamily: inputFontFamily,
365
- },
366
- {
367
- color: textColor,
368
- },
369
- ]}
287
+ style={[textStyle, styles.moneyTextInput, { color: textColor }]}
370
288
  allowFontScaling={false}
371
289
  textBreakStrategy="highQuality"
372
290
  value={displayValue}
291
+ selection={caretSelection ?? props.selection}
373
292
  onChangeText={_onChangeText}
374
- onSelectionChange={_onSelectionChange}
375
293
  onFocus={_onFocus}
376
294
  onBlur={_onBlur}
377
- placeholder={placeholder}
295
+ placeholder={inputPlaceholder}
378
296
  selectionColor={theme.colors.primary}
379
297
  placeholderTextColor={placeholderColor}
380
298
  keyboardType={'numeric'}
381
299
  maxLength={undefined}
382
300
  />
383
- </View>
301
+ {displayValue || placeholderHasCurrency ? (
302
+ <Text
303
+ style={[
304
+ textStyle,
305
+ { color: displayValue ? textColor : placeholderColor },
306
+ ]}
307
+ allowFontScaling={false}
308
+ >
309
+ {currency}
310
+ </Text>
311
+ ) : null}
312
+ </Pressable>
384
313
  <View style={styles.iconView}>
385
314
  {showClearIcon && focused && displayValue ? (
386
315
  <TouchableOpacity
@@ -64,8 +64,8 @@ const OTPCaret: FC<CaretProps> = ({ index, length }) => {
64
64
  opacity: opacity.value,
65
65
  }));
66
66
 
67
- const spacingStyle = !isNaN(Number(length)) &&
68
- index !== Number(length) - 1 && { marginRight: Spacing.L };
67
+ const hasNextInput = !isNaN(Number(length)) && index !== Number(length) - 1;
68
+ const spacingStyle = hasNextInput && { marginRight: Spacing.L };
69
69
 
70
70
  return (
71
71
  <View style={[Styles.rowCenter, spacingStyle]}>
@@ -162,6 +162,7 @@ const InputOTP = forwardRef(
162
162
 
163
163
  const renderInputs = (inputLength: number) => {
164
164
  const TextInputs: React.ReactNode[] = [];
165
+ const textColors = theme.colors.text;
165
166
  for (let i = 0; i < inputLength; i++) {
166
167
  TextInputs.push(
167
168
  <View key={`otp-input-${i}`}>
@@ -170,9 +171,7 @@ const InputOTP = forwardRef(
170
171
  ) : (
171
172
  <Text
172
173
  style={i !== inputLength - 1 && { marginRight: Spacing.L }}
173
- color={
174
- value[i] ? theme.colors.text.default : theme.colors.text.hint
175
- }
174
+ color={value[i] ? textColors.default : textColors.hint}
176
175
  typography={value[i] ? 'header_m_bold' : 'body_default_regular'}
177
176
  >
178
177
  {value[i] || '-'}
@@ -201,16 +200,14 @@ const InputOTP = forwardRef(
201
200
  return (
202
201
  <View style={Styles.row}>
203
202
  {splitValue.map((letter, index) => {
203
+ const isLast = index === value.length - 1;
204
+ const isTyping = focused && value.length !== MAX_LENGTH;
205
+ const isCompact = fontScale > 1 && value.length > 6;
206
+ const marginRight = isCompact ? Spacing.M : Spacing.L;
204
207
  return (
205
208
  <Text
206
209
  key={`otp-letter-${index}`}
207
- style={
208
- (index !== value.length - 1 ||
209
- (focused && value.length !== MAX_LENGTH)) && {
210
- marginRight:
211
- fontScale > 1 && value.length > 6 ? Spacing.M : Spacing.L,
212
- }
213
- }
210
+ style={(!isLast || isTyping) && { marginRight }}
214
211
  typography={'header_m_bold'}
215
212
  >
216
213
  {letter}
@@ -6,10 +6,9 @@ import React, {
6
6
  useState,
7
7
  } from 'react';
8
8
  import {
9
- NativeSyntheticEvent,
10
9
  StyleSheet,
11
10
  TextInput,
12
- TextInputFocusEventData,
11
+ TextInputFocusEvent,
13
12
  TouchableOpacity,
14
13
  View,
15
14
  } from 'react-native';
@@ -93,12 +92,12 @@ const InputPhoneNumber = forwardRef(
93
92
  onChangeText?.(text);
94
93
  };
95
94
 
96
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
95
+ const _onFocus = (e: TextInputFocusEvent) => {
97
96
  setFocused(true);
98
97
  onFocus?.(e);
99
98
  };
100
99
 
101
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
100
+ const _onBlur = (e: TextInputFocusEvent) => {
102
101
  setFocused(false);
103
102
  onBlur?.(e);
104
103
  };
@@ -10,9 +10,8 @@ import React, {
10
10
  useState,
11
11
  } from 'react';
12
12
  import {
13
- NativeSyntheticEvent,
14
13
  TextInput,
15
- TextInputFocusEventData,
14
+ TextInputFocusEvent,
16
15
  TouchableOpacity,
17
16
  View,
18
17
  } from 'react-native';
@@ -59,9 +58,11 @@ const TextTyping: FC<any> = ({
59
58
  listChar.length !== 0 && showChar(listChar?.[currentCharIndex.current]);
60
59
  };
61
60
 
62
- currentIndex.current >= data?.length
63
- ? handleResetList()
64
- : handleAnimation();
61
+ if (currentIndex.current >= data?.length) {
62
+ handleResetList();
63
+ } else {
64
+ handleAnimation();
65
+ }
65
66
  };
66
67
 
67
68
  const showChar = (char?: string) => {
@@ -82,9 +83,12 @@ const TextTyping: FC<any> = ({
82
83
  }, timeDelayNextChar);
83
84
  };
84
85
 
85
- currentCharIndex.current >= (data?.[currentIndex.current]?.length || 0)
86
- ? handleResetString()
87
- : handleShowChar();
86
+ const textLength = data?.[currentIndex.current]?.length || 0;
87
+ if (currentCharIndex.current >= textLength) {
88
+ handleResetString();
89
+ } else {
90
+ handleShowChar();
91
+ }
88
92
  };
89
93
 
90
94
  const reset = () => {
@@ -166,12 +170,12 @@ const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
166
170
  props.accessibilityLabel,
167
171
  );
168
172
 
169
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
173
+ const _onFocus = (e: TextInputFocusEvent) => {
170
174
  setFocused(true);
171
175
  onFocus?.(e);
172
176
  };
173
177
 
174
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
178
+ const _onBlur = (e: TextInputFocusEvent) => {
175
179
  setFocused(false);
176
180
  onBlur?.(e);
177
181
  };
@@ -303,6 +307,8 @@ const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
303
307
  inputState = 'filled';
304
308
  }
305
309
 
310
+ const inputBackground = backgroundColor ?? theme.colors.background.surface;
311
+
306
312
  return (
307
313
  <ComponentContext.Provider
308
314
  value={{
@@ -322,10 +328,7 @@ const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
322
328
  <View
323
329
  style={[
324
330
  styles.searchInputWrapper,
325
- {
326
- backgroundColor:
327
- backgroundColor ?? theme.colors.background.surface,
328
- },
331
+ { backgroundColor: inputBackground },
329
332
  ]}
330
333
  >
331
334
  <Icon
@@ -7,9 +7,8 @@ import React, {
7
7
  useState,
8
8
  } from 'react';
9
9
  import {
10
- NativeSyntheticEvent,
11
10
  TextInput,
12
- TextInputFocusEventData,
11
+ TextInputFocusEvent,
13
12
  TouchableOpacity,
14
13
  View,
15
14
  } from 'react-native';
@@ -79,12 +78,12 @@ const InputTextArea = forwardRef(
79
78
  setInputValue(text);
80
79
  };
81
80
 
82
- const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
81
+ const _onFocus = (e: TextInputFocusEvent) => {
83
82
  setFocused(true);
84
83
  onFocus?.(e);
85
84
  };
86
85
 
87
- const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
86
+ const _onBlur = (e: TextInputFocusEvent) => {
88
87
  setFocused(false);
89
88
  onBlur?.(e);
90
89
  };
@@ -17,11 +17,10 @@ const SystemTextInput: FC<SystemTextInputProps> = props => {
17
17
  const needsAndroidWrapper =
18
18
  Platform.OS === 'android' && !editable && (onPressIn || onPressOut);
19
19
 
20
+ const noPressHandlers = { onPressIn: undefined, onPressOut: undefined };
20
21
  const inputProps: TextInputProps = {
21
22
  ...props,
22
- ...(needsAndroidWrapper
23
- ? { onPressIn: undefined, onPressOut: undefined }
24
- : null),
23
+ ...(needsAndroidWrapper ? noPressHandlers : null),
25
24
  ...(editable === false ? { accessibilityState: undefined } : null),
26
25
  };
27
26
 
@@ -36,9 +36,11 @@ const TextTyping: FC<TextTypingProps> = ({
36
36
  listChar.length !== 0 && showChar(listChar?.[currentCharIndex.current]);
37
37
  };
38
38
 
39
- currentIndex.current >= data?.length
40
- ? handleResetList()
41
- : handleAnimation();
39
+ if (currentIndex.current >= data?.length) {
40
+ handleResetList();
41
+ } else {
42
+ handleAnimation();
43
+ }
42
44
  };
43
45
 
44
46
  const showChar = (char?: string) => {
@@ -59,9 +61,12 @@ const TextTyping: FC<TextTypingProps> = ({
59
61
  }, timeDelayNextChar);
60
62
  };
61
63
 
62
- currentCharIndex.current >= (data?.[currentIndex.current]?.length || 0)
63
- ? handleResetString()
64
- : handleShowChar();
64
+ const textLength = data?.[currentIndex.current]?.length || 0;
65
+ if (currentCharIndex.current >= textLength) {
66
+ handleResetString();
67
+ } else {
68
+ handleShowChar();
69
+ }
65
70
  };
66
71
 
67
72
  const reset = () => {
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
  });