@momo-kits/foundation 0.168.1-beta.3 → 0.168.1-beta.4
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 +33 -13
- package/package.json +1 -1
package/Input/InputMoney.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import React, {
|
|
|
8
8
|
useState,
|
|
9
9
|
} from 'react';
|
|
10
10
|
import {
|
|
11
|
+
Platform,
|
|
11
12
|
TextInput,
|
|
12
13
|
TextInputFocusEvent,
|
|
13
14
|
TouchableOpacity,
|
|
@@ -74,6 +75,7 @@ const InputMoney = forwardRef(
|
|
|
74
75
|
const [numericValue, setNumericValue] = useState('');
|
|
75
76
|
const [lastDisplayValue, setLastDisplayValue] = useState('');
|
|
76
77
|
const inputRef = useRef<TextInput>(null);
|
|
78
|
+
const caretDigitsAfter = useRef<number | undefined>(undefined);
|
|
77
79
|
const componentName = 'InputMoney';
|
|
78
80
|
|
|
79
81
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
@@ -91,14 +93,28 @@ const InputMoney = forwardRef(
|
|
|
91
93
|
if (value !== undefined && typeof value === 'string') {
|
|
92
94
|
const cleanValue = value.replace(/\D/g, '').replace(/^0+(?=\d)/, '');
|
|
93
95
|
if (cleanValue !== numericValue) {
|
|
96
|
+
caretDigitsAfter.current = undefined;
|
|
94
97
|
setNumericValue(cleanValue);
|
|
95
98
|
updateDisplayValue(cleanValue);
|
|
96
99
|
}
|
|
97
100
|
}
|
|
98
101
|
}, [value]);
|
|
99
102
|
|
|
103
|
+
// Android moves the caret proportionally when the text is replaced, so it
|
|
104
|
+
// lands before the typed digit once a separator is added. Put it back after
|
|
105
|
+
// the same digit.
|
|
100
106
|
useEffect(() => {
|
|
101
107
|
setLastDisplayValue(displayValue);
|
|
108
|
+
const digitsAfter = caretDigitsAfter.current;
|
|
109
|
+
caretDigitsAfter.current = undefined;
|
|
110
|
+
if (Platform.OS !== 'android' || digitsAfter === undefined) return;
|
|
111
|
+
let before = parseInputText(displayValue).length - digitsAfter;
|
|
112
|
+
let caret = 0;
|
|
113
|
+
while (before > 0 && caret < displayValue.length) {
|
|
114
|
+
if (/\d/.test(displayValue[caret])) before -= 1;
|
|
115
|
+
caret += 1;
|
|
116
|
+
}
|
|
117
|
+
inputRef.current?.setSelection(caret, caret);
|
|
102
118
|
}, [displayValue]);
|
|
103
119
|
|
|
104
120
|
const updateDisplayValue = (numeric: string) => {
|
|
@@ -142,19 +158,22 @@ const InputMoney = forwardRef(
|
|
|
142
158
|
onChangeText?.('');
|
|
143
159
|
return;
|
|
144
160
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
161
|
+
const old = lastDisplayValue;
|
|
162
|
+
let start = 0;
|
|
163
|
+
while (start < text.length && old[start] === text[start]) {
|
|
164
|
+
start += 1;
|
|
165
|
+
}
|
|
166
|
+
let suffix = 0;
|
|
167
|
+
while (
|
|
168
|
+
suffix < Math.min(text.length, old.length) - start &&
|
|
169
|
+
old[old.length - 1 - suffix] === text[text.length - 1 - suffix]
|
|
170
|
+
) {
|
|
171
|
+
suffix += 1;
|
|
172
|
+
}
|
|
173
|
+
caretDigitsAfter.current = text
|
|
174
|
+
.slice(text.length - suffix)
|
|
175
|
+
.replace(/\D/g, '').length;
|
|
176
|
+
if (text.length < old.length) {
|
|
158
177
|
const removed = old.slice(start, old.length - suffix);
|
|
159
178
|
if (!/\d/.test(removed)) {
|
|
160
179
|
const index = removed.includes('.')
|
|
@@ -183,6 +202,7 @@ const InputMoney = forwardRef(
|
|
|
183
202
|
};
|
|
184
203
|
|
|
185
204
|
const _setText = (text: string) => {
|
|
205
|
+
caretDigitsAfter.current = undefined;
|
|
186
206
|
if (!text) {
|
|
187
207
|
setDisplayValue('');
|
|
188
208
|
setNumericValue('');
|