@momo-kits/calculator-keyboard 0.151.2-beta.2 → 0.152.1-beta.2
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/android/src/main/java/com/calculatorkeyboard/CustomKeyboardView.kt +55 -3
- package/android/src/main/java/com/calculatorkeyboard/InputCalculatorViewManager.kt +11 -0
- package/android/src/main/res/drawable/ic_back.xml +9 -0
- package/ios/CalculatorKeyboardView.h +1 -0
- package/ios/CalculatorKeyboardView.mm +24 -29
- package/ios/NativeInputCalculator.mm +11 -0
- package/package.json +1 -1
- package/src/InputCalculatorNativeComponent.ts +1 -0
- package/src/index.tsx +3 -0
|
@@ -6,6 +6,7 @@ import android.graphics.Color
|
|
|
6
6
|
import android.graphics.drawable.GradientDrawable
|
|
7
7
|
import android.text.Editable
|
|
8
8
|
import android.view.Gravity
|
|
9
|
+
import android.view.MotionEvent
|
|
9
10
|
import android.widget.Button
|
|
10
11
|
import android.widget.EditText
|
|
11
12
|
import android.widget.ImageButton
|
|
@@ -130,6 +131,7 @@ class CustomKeyboardView(
|
|
|
130
131
|
translationX = xOffset.toInt().toFloat()
|
|
131
132
|
translationY = yOffset.toInt().toFloat()
|
|
132
133
|
setOnClickListener { onKeyPress(key, isMainCTAKey) }
|
|
134
|
+
applyTextPressedOpacity()
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
@@ -161,9 +163,56 @@ class CustomKeyboardView(
|
|
|
161
163
|
|
|
162
164
|
translationX = xOffset
|
|
163
165
|
translationY = yOffset
|
|
164
|
-
setImageResource(
|
|
166
|
+
setImageResource(R.drawable.ic_back)
|
|
165
167
|
setImageTintList(ColorStateList.valueOf(Color.BLACK))
|
|
166
168
|
setOnClickListener { onKeyPress(key, false) }
|
|
169
|
+
applyImagePressedOpacity()
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@SuppressLint("ClickableViewAccessibility")
|
|
174
|
+
private fun Button.applyTextPressedOpacity(
|
|
175
|
+
pressedAlpha: Float = 0.2f,
|
|
176
|
+
disabledAlpha: Float = 0.2f
|
|
177
|
+
) {
|
|
178
|
+
fun updateColorAlpha(alpha: Float) {
|
|
179
|
+
val color = textColors.defaultColor
|
|
180
|
+
val a = (alpha * 255).toInt().coerceIn(0, 255)
|
|
181
|
+
val rgb = color and 0x00FFFFFF
|
|
182
|
+
setTextColor((a shl 24) or rgb)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
updateColorAlpha(if (isEnabled) 1f else disabledAlpha)
|
|
186
|
+
|
|
187
|
+
setOnTouchListener { v, ev ->
|
|
188
|
+
when (ev.actionMasked) {
|
|
189
|
+
MotionEvent.ACTION_DOWN -> if (isEnabled) updateColorAlpha(pressedAlpha)
|
|
190
|
+
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL ->
|
|
191
|
+
updateColorAlpha(if (isEnabled) 1f else disabledAlpha)
|
|
192
|
+
}
|
|
193
|
+
false
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@SuppressLint("ClickableViewAccessibility")
|
|
198
|
+
fun ImageButton.applyImagePressedOpacity(
|
|
199
|
+
pressedAlpha: Float = 0.2f,
|
|
200
|
+
disabledAlpha: Float = 0.2f
|
|
201
|
+
) {
|
|
202
|
+
fun updateImageAlpha(alpha: Float) {
|
|
203
|
+
drawable?.mutate()?.alpha = (alpha * 255).toInt().coerceIn(0, 255)
|
|
204
|
+
invalidate()
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
updateImageAlpha(if (isEnabled) 1f else disabledAlpha)
|
|
208
|
+
|
|
209
|
+
setOnTouchListener { _, ev ->
|
|
210
|
+
when (ev.actionMasked) {
|
|
211
|
+
MotionEvent.ACTION_DOWN -> if (isEnabled) updateImageAlpha(pressedAlpha)
|
|
212
|
+
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL ->
|
|
213
|
+
updateImageAlpha(if (isEnabled) 1f else disabledAlpha)
|
|
214
|
+
}
|
|
215
|
+
false
|
|
167
216
|
}
|
|
168
217
|
}
|
|
169
218
|
|
|
@@ -183,11 +232,14 @@ class CustomKeyboardView(
|
|
|
183
232
|
Event.emitKeyPress(context, editText.id, key)
|
|
184
233
|
|
|
185
234
|
val text = editText.text ?: return
|
|
235
|
+
val cursorPos = editText.selectionStart
|
|
186
236
|
val plain = text.toString()
|
|
187
|
-
val
|
|
237
|
+
val isStartPosition = cursorPos == 72 || cursorPos == 0
|
|
188
238
|
val isJustZero = plain == "0"
|
|
189
239
|
val endsWithOperator = plain.endsWithAny(" + ", " - ", " × ", " ÷ ")
|
|
190
240
|
val endsWithSingleZeroAfterOp = plain.endsWith(" 0")
|
|
241
|
+
val posBeforeOperator = text.substring(0, cursorPos).endsWithAny(" + ", " - ", " × ", " ÷ ")
|
|
242
|
+
&& editText.length() > cursorPos
|
|
191
243
|
|
|
192
244
|
when (key) {
|
|
193
245
|
"AC" -> clearText()
|
|
@@ -196,7 +248,7 @@ class CustomKeyboardView(
|
|
|
196
248
|
"×", "+", "-", "÷" -> if (!text.isEmpty()) keyDidPress(" $key ")
|
|
197
249
|
"0", "000" -> {
|
|
198
250
|
when {
|
|
199
|
-
|
|
251
|
+
isStartPosition || posBeforeOperator -> {}
|
|
200
252
|
key == "000" && endsWithOperator -> text.insertAtCaret(editText, "0")
|
|
201
253
|
endsWithSingleZeroAfterOp || isJustZero -> {}
|
|
202
254
|
else -> text.insertAtCaret(editText, key)
|
|
@@ -9,6 +9,7 @@ import android.text.Editable
|
|
|
9
9
|
import android.text.TextWatcher
|
|
10
10
|
import android.view.KeyEvent
|
|
11
11
|
import android.view.inputmethod.InputMethodManager
|
|
12
|
+
import androidx.annotation.RequiresApi
|
|
12
13
|
import androidx.core.graphics.toColorInt
|
|
13
14
|
import androidx.core.view.ViewCompat
|
|
14
15
|
import androidx.core.view.WindowInsetsCompat
|
|
@@ -112,6 +113,16 @@ class InputCalculatorViewManager : SimpleViewManager<ReactEditText>(), NativeInp
|
|
|
112
113
|
keyboardView?.setMode(mode ?: "NumDefault")
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
@RequiresApi(Build.VERSION_CODES.Q)
|
|
117
|
+
override fun setSelectionColor(
|
|
118
|
+
view: ReactEditText?,
|
|
119
|
+
value: String?
|
|
120
|
+
) {
|
|
121
|
+
if (value == null) return
|
|
122
|
+
view?.highlightColor = value.toColorInt()
|
|
123
|
+
view?.textCursorDrawable?.setTint(value.toColorInt())
|
|
124
|
+
}
|
|
125
|
+
|
|
115
126
|
@ReactProp(name = "customKeyText")
|
|
116
127
|
override fun setCustomKeyText(view: ReactEditText, text: String?) {
|
|
117
128
|
keyboardView?.setCustomKeyText(text ?: "Tiếp")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
android:width="24dp"
|
|
3
|
+
android:height="24dp"
|
|
4
|
+
android:viewportWidth="960"
|
|
5
|
+
android:viewportHeight="960">
|
|
6
|
+
<path
|
|
7
|
+
android:pathData="m456,640 l104,-104 104,104 56,-56 -104,-104 104,-104 -56,-56 -104,104 -104,-104 -56,56 104,104 -104,104 56,56ZM360,800q-19,0 -36,-8.5T296,768L80,480l216,-288q11,-15 28,-23.5t36,-8.5h440q33,0 56.5,23.5T880,240v480q0,33 -23.5,56.5T800,800L360,800ZM180,480l180,240h440v-480L360,240L180,480ZM580,480Z"
|
|
8
|
+
android:fillColor="#1f1f1f"/>
|
|
9
|
+
</vector>
|
|
@@ -198,23 +198,24 @@
|
|
|
198
198
|
|
|
199
199
|
[self.input emitKeyPress:key];
|
|
200
200
|
|
|
201
|
-
NSString *text = self.input
|
|
202
|
-
|
|
201
|
+
NSString *text = [self.input getText] ?: @"";
|
|
202
|
+
NSInteger cursorPos = [self.input getCursorPosition];
|
|
203
203
|
BOOL isJustZero = [text isEqualToString:@"0"];
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
BOOL
|
|
207
|
-
BOOL endsWithMul = [text hasSuffix:@" × "];
|
|
208
|
-
BOOL endsWithDiv = [text hasSuffix:@" ÷ "];
|
|
209
|
-
BOOL endsWithOperator = (endsWithPlus || endsWithMinus || endsWithMul || endsWithDiv);
|
|
210
|
-
|
|
205
|
+
NSArray<NSString *> *ops = @[ @" + ", @" - ", @" × ", @" ÷ " ];
|
|
206
|
+
BOOL endsWithOperator = endsWithAny(text, ops);
|
|
211
207
|
BOOL endsWithSingleZeroAfterOp = [text hasSuffix:@" 0"];
|
|
212
208
|
|
|
209
|
+
BOOL isStartPosition = (cursorPos == 72 || cursorPos == 0);
|
|
210
|
+
NSString *prefix = (cursorPos > 0 && cursorPos <= (NSInteger)text.length)
|
|
211
|
+
? [text substringToIndex:cursorPos] : @"";
|
|
212
|
+
BOOL posBeforeOperator = endsWithAny(prefix, ops) && (text.length > (NSUInteger)cursorPos);
|
|
213
|
+
|
|
213
214
|
BOOL (^isOpKey)(NSString *) = ^BOOL(NSString *k) {
|
|
214
215
|
return [k isEqualToString:@"+"] || [k isEqualToString:@"-"] ||
|
|
215
216
|
[k isEqualToString:@"×"] || [k isEqualToString:@"÷"];
|
|
216
217
|
};
|
|
217
|
-
void (^
|
|
218
|
+
void (^insertAtCaret)(NSString *) = ^(NSString *s) { [self.input keyDidPress:s]; };
|
|
218
219
|
void (^replaceTrailingZeroWith)(NSString *) = ^(NSString *s) {
|
|
219
220
|
[self.input onBackSpace];
|
|
220
221
|
[self.input keyDidPress:s];
|
|
@@ -224,39 +225,28 @@
|
|
|
224
225
|
[self.input keyDidPress:s];
|
|
225
226
|
};
|
|
226
227
|
|
|
227
|
-
if ([key isEqualToString:@"AC"]) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if ([key isEqualToString:@"back"]) {
|
|
233
|
-
[self.input onBackSpace];
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if ([key isEqualToString:@"="]) {
|
|
238
|
-
[self.input calculateResult];
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
228
|
+
if ([key isEqualToString:@"AC"]) { [self.input clearText]; return; }
|
|
229
|
+
if ([key isEqualToString:@"back"]) { [self.input onBackSpace]; return; }
|
|
230
|
+
if ([key isEqualToString:@"="]) { [self.input calculateResult]; return; }
|
|
241
231
|
|
|
242
232
|
if (isOpKey(key)) {
|
|
243
|
-
if (
|
|
244
|
-
|
|
233
|
+
if (text.length > 0) {
|
|
234
|
+
insertAtCaret([NSString stringWithFormat:@" %@ ", key]);
|
|
245
235
|
}
|
|
246
236
|
return;
|
|
247
237
|
}
|
|
248
238
|
|
|
249
239
|
if ([key isEqualToString:@"0"] || [key isEqualToString:@"000"]) {
|
|
250
|
-
if (
|
|
240
|
+
if (isStartPosition || posBeforeOperator) return;
|
|
251
241
|
|
|
252
242
|
if ([key isEqualToString:@"000"] && endsWithOperator) {
|
|
253
|
-
|
|
243
|
+
insertAtCaret(@"0");
|
|
254
244
|
return;
|
|
255
245
|
}
|
|
256
246
|
|
|
257
247
|
if (endsWithSingleZeroAfterOp || isJustZero) return;
|
|
258
248
|
|
|
259
|
-
|
|
249
|
+
insertAtCaret(key);
|
|
260
250
|
return;
|
|
261
251
|
}
|
|
262
252
|
|
|
@@ -265,10 +255,15 @@
|
|
|
265
255
|
} else if (endsWithSingleZeroAfterOp) {
|
|
266
256
|
replaceTrailingZeroWith(key);
|
|
267
257
|
} else {
|
|
268
|
-
|
|
258
|
+
insertAtCaret(key);
|
|
269
259
|
}
|
|
270
260
|
}
|
|
271
261
|
|
|
272
262
|
|
|
263
|
+
static BOOL endsWithAny(NSString *text, NSArray<NSString *> *suffixes) {
|
|
264
|
+
for (NSString *s in suffixes) { if ([text hasSuffix:s]) return YES; }
|
|
265
|
+
return NO;
|
|
266
|
+
}
|
|
267
|
+
|
|
273
268
|
@end
|
|
274
269
|
|
|
@@ -140,6 +140,10 @@ using namespace facebook::react;
|
|
|
140
140
|
}];
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
if (oldViewProps.selectionColor != newViewProps.selectionColor) {
|
|
144
|
+
_textField.tintColor = [Utils colorFromHex:RCTNSStringFromString(newViewProps.selectionColor)];
|
|
145
|
+
}
|
|
146
|
+
|
|
143
147
|
[super updateProps:props oldProps:oldProps];
|
|
144
148
|
}
|
|
145
149
|
|
|
@@ -490,6 +494,13 @@ static UIFontWeight _UIFontWeightFromString(std::string_view s) {
|
|
|
490
494
|
}
|
|
491
495
|
}
|
|
492
496
|
|
|
497
|
+
- (NSInteger)getCursorPosition
|
|
498
|
+
{
|
|
499
|
+
UITextRange *sel = _textField.selectedTextRange;
|
|
500
|
+
if (!sel) return 0;
|
|
501
|
+
return [_textField offsetFromPosition:_textField.beginningOfDocument
|
|
502
|
+
toPosition:sel.start];
|
|
503
|
+
}
|
|
493
504
|
|
|
494
505
|
@end
|
|
495
506
|
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -21,6 +21,7 @@ type KeyPressEvent = { nativeEvent: { key: string } };
|
|
|
21
21
|
interface InputCalculatorProps extends TextInputProps {
|
|
22
22
|
text?: string | undefined;
|
|
23
23
|
mode?: Mode;
|
|
24
|
+
selectionColor?: string | undefined;
|
|
24
25
|
onBlur?: () => void;
|
|
25
26
|
onFocus?: () => void;
|
|
26
27
|
onResult?: (e: OnResultEvent) => void;
|
|
@@ -83,6 +84,7 @@ const InputCalculator = React.forwardRef<
|
|
|
83
84
|
{
|
|
84
85
|
customKeyBackground = 'default',
|
|
85
86
|
mode = Mode.NumDefault,
|
|
87
|
+
selectionColor,
|
|
86
88
|
customKeyText,
|
|
87
89
|
onBlur,
|
|
88
90
|
onFocus,
|
|
@@ -147,6 +149,7 @@ const InputCalculator = React.forwardRef<
|
|
|
147
149
|
onKeyPress={onKeyPress}
|
|
148
150
|
value={text}
|
|
149
151
|
mode={mode}
|
|
152
|
+
selectionColor={selectionColor}
|
|
150
153
|
customKeyText={customKeyText}
|
|
151
154
|
customKeyBackground={keyBackground}
|
|
152
155
|
customKeyTextColor={textKeyColor}
|