@momo-kits/calculator-keyboard 0.150.2-phuc.15 → 0.151.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.
Files changed (30) hide show
  1. package/README.md +45 -3
  2. package/android/src/main/java/com/calculatorkeyboard/CalculatorKeyboardPackage.kt +1 -1
  3. package/android/src/main/java/com/calculatorkeyboard/CustomKeyboardView.kt +242 -108
  4. package/android/src/main/java/com/calculatorkeyboard/Event.kt +129 -0
  5. package/android/src/main/java/com/calculatorkeyboard/{RCTInputCalculator.kt → InputCalculatorViewManager.kt} +105 -33
  6. package/ios/CalculatorKeyboardView.h +32 -0
  7. package/ios/CalculatorKeyboardView.mm +274 -0
  8. package/ios/NativeInputCalculator.h +11 -0
  9. package/ios/NativeInputCalculator.mm +500 -0
  10. package/ios/Utils.h +10 -0
  11. package/ios/Utils.mm +25 -0
  12. package/package.json +21 -131
  13. package/react-native-calculator-keyboard.podspec +5 -4
  14. package/src/InputCalculatorNativeComponent.ts +71 -0
  15. package/src/index.tsx +93 -43
  16. package/ios/CalculatorKeyboardView.swift +0 -153
  17. package/ios/InputCalculator-Bridging-Header.h +0 -23
  18. package/ios/InputCalculator.m +0 -85
  19. package/ios/InputCalculator.swift +0 -158
  20. package/ios/extension.swift +0 -23
  21. package/lib/commonjs/index.js +0 -72
  22. package/lib/commonjs/index.js.map +0 -1
  23. package/lib/module/index.js +0 -67
  24. package/lib/module/index.js.map +0 -1
  25. package/lib/typescript/commonjs/package.json +0 -1
  26. package/lib/typescript/commonjs/src/index.d.ts +0 -23
  27. package/lib/typescript/commonjs/src/index.d.ts.map +0 -1
  28. package/lib/typescript/module/package.json +0 -1
  29. package/lib/typescript/module/src/index.d.ts +0 -23
  30. package/lib/typescript/module/src/index.d.ts.map +0 -1
@@ -3,20 +3,36 @@ package com.calculatorkeyboard
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
5
  import android.graphics.Color
6
+ import android.graphics.Typeface
7
+ import android.os.Build
8
+ import android.text.Editable
9
+ import android.text.TextWatcher
6
10
  import android.view.KeyEvent
7
11
  import android.view.inputmethod.InputMethodManager
8
12
  import androidx.core.graphics.toColorInt
9
13
  import androidx.core.view.ViewCompat
10
14
  import androidx.core.view.WindowInsetsCompat
11
- import com.facebook.react.bridge.ReadableArray
15
+ import com.calculatorkeyboard.CustomKeyboardView.Companion.calculateResult
16
+ import com.facebook.react.bridge.ReadableMap
12
17
  import com.facebook.react.bridge.UiThreadUtil
18
+ import com.facebook.react.module.annotations.ReactModule
13
19
  import com.facebook.react.uimanager.PixelUtil.dpToPx
20
+ import com.facebook.react.uimanager.SimpleViewManager
14
21
  import com.facebook.react.uimanager.ThemedReactContext
22
+ import com.facebook.react.uimanager.ViewManagerDelegate
15
23
  import com.facebook.react.uimanager.annotations.ReactProp
24
+ import com.facebook.react.viewmanagers.NativeInputCalculatorManagerDelegate
25
+ import com.facebook.react.viewmanagers.NativeInputCalculatorManagerInterface
16
26
  import com.facebook.react.views.textinput.ReactEditText
17
- import com.facebook.react.views.textinput.ReactTextInputManager
18
27
 
19
- class RCTInputCalculator : ReactTextInputManager() {
28
+ @ReactModule(name = InputCalculatorViewManager.REACT_CLASS)
29
+ class InputCalculatorViewManager : SimpleViewManager<ReactEditText>(), NativeInputCalculatorManagerInterface<ReactEditText> {
30
+ private val delegate: NativeInputCalculatorManagerDelegate<ReactEditText, InputCalculatorViewManager> =
31
+ NativeInputCalculatorManagerDelegate(this)
32
+
33
+ override fun getDelegate(): ViewManagerDelegate<ReactEditText> = delegate
34
+
35
+ override fun getName() = REACT_CLASS
20
36
 
21
37
  private var keyboardView: CustomKeyboardView? = null
22
38
  private lateinit var editText: CalculatorEditText
@@ -27,15 +43,14 @@ class RCTInputCalculator : ReactTextInputManager() {
27
43
  private var backListenerAttached = false
28
44
  private var overlayShowing = false
29
45
 
30
- override fun getName() = REACT_CLASS
31
46
 
32
47
  companion object {
33
- const val REACT_CLASS = "RCTInputCalculator"
48
+ const val REACT_CLASS = "NativeInputCalculator"
34
49
  val calculatorHeight: Int = 240.dpToPx().toInt()
35
50
  }
36
51
 
37
52
  @ReactProp(name = "value")
38
- fun setValue(view: ReactEditText, value: String?) {
53
+ override fun setValue(view: ReactEditText, value: String?) {
39
54
  UiThreadUtil.runOnUiThread {
40
55
  val e = view.editableText ?: run { view.setText(value ?: ""); return@runOnUiThread }
41
56
  val newText = value ?: ""
@@ -45,32 +60,84 @@ class RCTInputCalculator : ReactTextInputManager() {
45
60
  val atEnd = wasFocused && view.selectionStart == e.length && view.selectionEnd == e.length
46
61
  e.replace(0, e.length, newText)
47
62
  if (!wasFocused || atEnd) view.setSelection(newText.length)
63
+ keyboardView?.reformatAndKeepSelection(editText)
48
64
  }
49
65
  }
50
66
 
67
+ override fun setTextAttributes(view: ReactEditText?, value: ReadableMap?) {
68
+ val fontWeightStr = value?.getString("fontWeight")
69
+ val fontSize = value?.getDouble("fontSize")
70
+ val placeHolder = value?.getString("placeholder")
71
+ val placeHolderTextColor = value?.getString("placeholderTextColor")
72
+
73
+ fontWeightStr?.let { weightStr ->
74
+ val weight = when (weightStr) {
75
+ "100" -> 100
76
+ "200" -> 200
77
+ "300" -> 300
78
+ "400", "normal" -> 400
79
+ "500" -> 500
80
+ "600" -> 600
81
+ "700", "bold" -> 700
82
+ "800" -> 800
83
+ "900" -> 900
84
+ else -> 400
85
+ }
86
+
87
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
88
+ view?.typeface = Typeface.create(view.typeface, weight, false)
89
+ } else {
90
+ view?.typeface = if (weight >= 600) {
91
+ Typeface.create(view.typeface, Typeface.BOLD)
92
+ } else {
93
+ Typeface.create(view.typeface, Typeface.NORMAL)
94
+ }
95
+ }
96
+ }
97
+
98
+ fontSize?.let {
99
+ view?.textSize = it.toFloat()
100
+ }
101
+ placeHolder?.let {
102
+ view?.setPlaceholder(placeHolder)
103
+ }
104
+ placeHolderTextColor?.let {
105
+ view?.setHintTextColor(it.toColorInt())
106
+ }
107
+ }
108
+
109
+
110
+ @ReactProp(name = "mode")
111
+ override fun setMode(view: ReactEditText, mode: String?) {
112
+ keyboardView?.setMode(mode ?: "NumDefault")
113
+ }
114
+
51
115
  @ReactProp(name = "customKeyText")
52
- fun setCustomKeyText(view: ReactEditText, text: String?) {
53
- keyboardView?.setCustomKeyText(text ?: "Xong")
116
+ override fun setCustomKeyText(view: ReactEditText, text: String?) {
117
+ keyboardView?.setCustomKeyText(text ?: "Tiếp")
54
118
  }
55
119
 
56
120
  @ReactProp(name = "customKeyBackground")
57
- fun setCustomKeyBackground(view: ReactEditText, background: String?) {
121
+ override fun setCustomKeyBackground(view: ReactEditText, background: String?) {
58
122
  keyboardView?.setCustomKeyBackground((background ?: "#d8d8d8").toColorInt())
59
123
  }
60
124
 
61
125
  @ReactProp(name = "customKeyTextColor")
62
- fun setCustomKeyTextColor(view: ReactEditText, textColor: String?) {
126
+ override fun setCustomKeyTextColor(view: ReactEditText, textColor: String?) {
63
127
  keyboardView?.setCustomKeyTextColor(textColor?.toColorInt() ?: Color.BLACK)
64
128
  }
65
129
 
66
130
  @ReactProp(name = "customKeyState")
67
- fun setCustomKeyState(view: ReactEditText, state: String?) {
131
+ override fun setCustomKeyState(view: ReactEditText, state: String?) {
68
132
  keyboardView?.setCustomKeyState(state ?: "default")
69
133
  }
70
134
 
71
- @ReactProp(name = "keyboardColor")
72
- fun setKeyboardColor(view: ReactEditText, color: String) {
73
- keyboardView?.updateButtonColors(color.toColorInt())
135
+ override fun focus(view: ReactEditText?) {
136
+ UiThreadUtil.runOnUiThread { if (!editText.isFocused) editText.requestFocus() }
137
+ }
138
+
139
+ override fun blur(view: ReactEditText?) {
140
+ UiThreadUtil.runOnUiThread { if (editText.isFocused) editText.clearFocus() }
74
141
  }
75
142
 
76
143
  @SuppressLint("ClickableViewAccessibility")
@@ -80,6 +147,8 @@ class RCTInputCalculator : ReactTextInputManager() {
80
147
  editText = CalculatorEditText(context).apply {
81
148
  showSoftInputOnFocus = false
82
149
  isFocusableInTouchMode = true
150
+ isSingleLine = true
151
+
83
152
  setOnTouchListener { v, event ->
84
153
  if (event.action == android.view.MotionEvent.ACTION_DOWN) {
85
154
  showSoftInputOnFocus = false
@@ -101,6 +170,21 @@ class RCTInputCalculator : ReactTextInputManager() {
101
170
  }
102
171
  false
103
172
  }
173
+ addTextChangedListener(object : TextWatcher{
174
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
175
+
176
+ override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
177
+
178
+ override fun afterTextChanged(s: Editable?) {
179
+ Event.emitOnChange(context, editText.id, s.toString())
180
+ Event.emitOnResult(context, editText.id, editText.calculateResult())
181
+ }
182
+
183
+ })
184
+
185
+ setOnFocusChangeListener { view, hasFocus ->
186
+ Event.emitOnBlurFocus(context, editText.id, hasFocus)
187
+ }
104
188
  }
105
189
 
106
190
  keyboardView = CustomKeyboardView(context, editText).apply {
@@ -155,7 +239,7 @@ class RCTInputCalculator : ReactTextInputManager() {
155
239
 
156
240
  private fun disableSystemImeFor(v: ReactEditText) {
157
241
  v.showSoftInputOnFocus = false
158
- if (android.os.Build.VERSION.SDK_INT >= 30) {
242
+ if (Build.VERSION.SDK_INT >= 30) {
159
243
  ViewCompat.getWindowInsetsController(v)?.hide(WindowInsetsCompat.Type.ime())
160
244
  }
161
245
  imm.hideSoftInputFromWindow(v.windowToken, 0)
@@ -165,33 +249,21 @@ class RCTInputCalculator : ReactTextInputManager() {
165
249
  v.showSoftInputOnFocus = true
166
250
  }
167
251
 
168
- override fun getCommandsMap(): Map<String, Int> = mapOf("blur" to 1, "focus" to 2)
169
-
170
- override fun receiveCommand(reactEditText: ReactEditText, commandId: Int, args: ReadableArray?) {
171
- when (commandId) {
172
- 1 -> blur()
173
- 2 -> focus()
174
- }
175
- }
176
-
177
252
  override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> {
178
- val base = super.getExportedCustomBubblingEventTypeConstants().toMutableMap()
253
+ val base = super.getExportedCustomBubblingEventTypeConstants()?.toMutableMap() ?: mutableMapOf()
179
254
  base["onKeyPress"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onKeyPress"))
255
+ base["onChange"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onChange"))
256
+ base["onResult"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onResult"))
180
257
  return base
181
258
  }
182
259
 
183
260
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
184
- val base = super.getExportedCustomDirectEventTypeConstants().toMutableMap()
261
+ val base = super.getExportedCustomDirectEventTypeConstants()?.toMutableMap() ?: mutableMapOf()
262
+ base["onBlur"] = mapOf("registrationName" to "onBlur")
263
+ base["onFocus"] = mapOf("registrationName" to "onFocus")
185
264
  base["onCustomKeyEvent"] = mapOf("registrationName" to "onCustomKeyEvent")
186
265
  return base
187
266
  }
188
267
 
189
- private fun focus() {
190
- UiThreadUtil.runOnUiThread { if (!editText.isFocused) editText.requestFocus() }
191
- }
192
-
193
- private fun blur() {
194
- UiThreadUtil.runOnUiThread { if (editText.isFocused) editText.clearFocus() }
195
- }
196
268
  }
197
269
 
@@ -0,0 +1,32 @@
1
+ #import <UIKit/UIKit.h>
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ @protocol CalculatorKeyboardInput <NSObject>
6
+
7
+ - (void)keyDidPress:(NSString *)key;
8
+ - (void)clearText;
9
+ - (NSString *)getText;
10
+ - (void)onBackSpace;
11
+ - (NSString *)calculate;
12
+ - (void)calculateResult;
13
+ - (void)emitCustomKey;
14
+ - (void)emitKeyPress:(NSString *)key;
15
+
16
+ @end
17
+
18
+ @interface CalculatorKeyboardView : UIView
19
+
20
+ @property (nonatomic, weak, nullable) id<CalculatorKeyboardInput> input;
21
+ @property (nonatomic, strong, nullable) NSString *keyboardMode;
22
+ @property (nonatomic, strong, nullable) NSString *customKeyText;
23
+ @property (nonatomic, strong, nullable) NSString *customKeyBackground;
24
+ @property (nonatomic, strong, nullable) NSString *customKeyTextColor;
25
+ @property (nonatomic, strong, nullable) NSString *customKeyState;
26
+
27
+ - (void)setKeyboardColor:(UIColor *)color;
28
+
29
+ @end
30
+
31
+ NS_ASSUME_NONNULL_END
32
+
@@ -0,0 +1,274 @@
1
+ #import "CalculatorKeyboardView.h"
2
+ #import "Utils.h"
3
+
4
+ @interface CalculatorKeyboardView ()
5
+ @property (nonatomic, strong) NSArray<NSArray<NSString *> *> *numWithCTAKeys;
6
+ @property (nonatomic, strong) NSArray<NSArray<NSString *> *> *defaultKeys;
7
+ @property (nonatomic, strong) NSSet<NSString *> *specialKeys;
8
+ @property (nonatomic, weak) UIButton *customKeyButton;
9
+ @end
10
+
11
+ @implementation CalculatorKeyboardView {
12
+ CGFloat _separatorWidth;
13
+ }
14
+
15
+ - (instancetype)initWithFrame:(CGRect)frame
16
+ {
17
+ if (self = [super initWithFrame:frame]) {
18
+ _separatorWidth = 4.0;
19
+
20
+ _numWithCTAKeys = @[
21
+ @[@"1", @"2", @"3", @"÷", @"back"],
22
+ @[@"4", @"5", @"6", @"×", @"="],
23
+ @[@"7", @"8", @"9", @"-", @"Tiếp"],
24
+ @[@"000", @"0", @"+"]
25
+ ];
26
+
27
+ _defaultKeys = @[
28
+ @[@"1", @"2", @"3", @"÷", @"AC"],
29
+ @[@"4", @"5", @"6", @"×", @"back"],
30
+ @[@"7", @"8", @"9", @"-", @"="],
31
+ @[@"000", @"0", @"+"]
32
+ ];
33
+
34
+ _specialKeys = [NSSet setWithArray:@[@"=", @"-", @"×", @"÷", @"back", @"+", @"AC"]];
35
+
36
+ [self setup];
37
+ }
38
+ return self;
39
+ }
40
+
41
+ - (void)setKeyboardMode:(NSString *)keyboardMode
42
+ {
43
+ if ([_keyboardMode isEqualToString:keyboardMode]) {
44
+ return;
45
+ }
46
+ _keyboardMode = keyboardMode;
47
+ [self setup];
48
+ }
49
+
50
+ - (void)setCustomKeyText:(NSString *)customKeyText
51
+ {
52
+ _customKeyText = customKeyText;
53
+ [self updateCustomKeyTitle];
54
+ }
55
+
56
+ - (void)setCustomKeyBackground:(NSString *)customKeyBackground
57
+ {
58
+ _customKeyBackground = customKeyBackground;
59
+ [self updateCustomKeyBackground];
60
+ }
61
+
62
+ - (void)setCustomKeyTextColor:(NSString *)customKeyTextColor
63
+ {
64
+ _customKeyTextColor = customKeyTextColor;
65
+ [self updateCustomKeyBackground];
66
+ }
67
+
68
+ - (void)setCustomKeyState:(NSString *)customKeyState
69
+ {
70
+ _customKeyState = customKeyState;
71
+ [self updateCustomKeyBackground];
72
+ }
73
+
74
+ - (void)setKeyboardColor:(UIColor *)color
75
+ {
76
+ [self setup];
77
+ }
78
+
79
+ - (void)setup
80
+ {
81
+ // Remove all subviews
82
+ for (UIView *subview in self.subviews) {
83
+ [subview removeFromSuperview];
84
+ }
85
+
86
+ self.backgroundColor = [Utils colorFromHex:@"#f2f2f6"];
87
+
88
+ CGFloat buttonWidth = (UIScreen.mainScreen.bounds.size.width - _separatorWidth * 2 - 4 * _separatorWidth) / 5;
89
+ CGFloat buttonHeight = (240 - _separatorWidth * 2 - 3 * _separatorWidth) / 4;
90
+
91
+ // Create content view
92
+ UIView *contentView = [[UIView alloc] init];
93
+ contentView.translatesAutoresizingMaskIntoConstraints = NO;
94
+ [self addSubview:contentView];
95
+
96
+ // Set contentView constraints
97
+ [NSLayoutConstraint activateConstraints:@[
98
+ [contentView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:_separatorWidth],
99
+ [contentView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-_separatorWidth],
100
+ [contentView.topAnchor constraintEqualToAnchor:self.topAnchor constant:_separatorWidth],
101
+ [contentView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-_separatorWidth]
102
+ ]];
103
+
104
+ CGFloat yOffset = 0;
105
+ NSArray<NSArray<NSString *> *> *keys = [_keyboardMode isEqualToString:@"NumDefault"] ? _defaultKeys : _numWithCTAKeys;
106
+
107
+ for (NSInteger rowIndex = 0; rowIndex < keys.count; rowIndex++) {
108
+ NSArray<NSString *> *row = keys[rowIndex];
109
+ CGFloat xOffset = 0;
110
+
111
+ for (NSInteger colIndex = 0; colIndex < row.count; colIndex++) {
112
+ NSString *key = row[colIndex];
113
+ BOOL isMainKey = (colIndex == 4 && rowIndex == 2);
114
+ BOOL isMainCTAKey = isMainKey && [_keyboardMode isEqualToString:@"NumWithCTA"];
115
+
116
+ UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
117
+ button.backgroundColor = UIColor.whiteColor;
118
+ button.layer.cornerRadius = 8;
119
+
120
+ NSString *title = isMainCTAKey ? (_customKeyText ?: key) : key;
121
+ [button setTitle:title forState:UIControlStateNormal];
122
+ [button setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
123
+ button.titleLabel.font = [UIFont systemFontOfSize:isMainCTAKey ? 18 : 24 weight:UIFontWeightMedium];
124
+ button.accessibilityIdentifier = key;
125
+ button.tag = isMainCTAKey ? 1 : 0;
126
+
127
+ CGRect buttonFrame = CGRectMake(xOffset, yOffset, buttonWidth, buttonHeight);
128
+ if (isMainKey) {
129
+ buttonFrame.size.height = buttonHeight * 2 + _separatorWidth;
130
+ }
131
+ if ([key isEqualToString:@"000"]) {
132
+ buttonFrame.size.width = buttonWidth * 2 + _separatorWidth;
133
+ }
134
+
135
+ button.frame = buttonFrame;
136
+
137
+ if ([key isEqualToString:@"back"]) {
138
+ [button setTitle:@"" forState:UIControlStateNormal];
139
+ UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithWeight:UIImageSymbolWeightBold];
140
+ UIImage *image = [UIImage systemImageNamed:@"delete.backward" withConfiguration:config];
141
+ [button setImage:image forState:UIControlStateNormal];
142
+ button.tintColor = UIColor.blackColor;
143
+ }
144
+
145
+ if ([_specialKeys containsObject:key] || isMainKey) {
146
+ [button setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
147
+ button.backgroundColor = [Utils colorFromHex:@"#d8d8d8"];
148
+ }
149
+
150
+ if (isMainKey) {
151
+ self.customKeyButton = button;
152
+ }
153
+
154
+ [button addTarget:self action:@selector(keyPressed:) forControlEvents:UIControlEventTouchUpInside];
155
+ [contentView addSubview:button];
156
+
157
+ xOffset += buttonFrame.size.width + _separatorWidth;
158
+ }
159
+
160
+ yOffset += buttonHeight + _separatorWidth;
161
+ }
162
+ }
163
+
164
+ - (void)updateCustomKeyTitle
165
+ {
166
+ if (!self.customKeyButton || !_customKeyText) {
167
+ return;
168
+ }
169
+ [self.customKeyButton setTitle:_customKeyText forState:UIControlStateNormal];
170
+ [self.customKeyButton setImage:nil forState:UIControlStateNormal];
171
+ }
172
+
173
+ - (void)updateCustomKeyBackground
174
+ {
175
+ if (!self.customKeyButton || !_keyboardMode || !_customKeyBackground || !_customKeyTextColor || !_customKeyState) {
176
+ return;
177
+ }
178
+
179
+ if ([_keyboardMode isEqualToString:@"numWithCTA"]) {
180
+ self.customKeyButton.enabled = ![_customKeyState isEqualToString:@"disable"];
181
+ } else {
182
+ self.customKeyButton.enabled = YES;
183
+ }
184
+
185
+ self.customKeyButton.backgroundColor = [Utils colorFromHex:_customKeyBackground];
186
+ [self.customKeyButton setTitleColor:[Utils colorFromHex:_customKeyTextColor] forState:UIControlStateNormal];
187
+ }
188
+
189
+ - (void)keyPressed:(UIButton *)sender
190
+ {
191
+ NSString *key = sender.accessibilityIdentifier;
192
+ if (!key) return;
193
+
194
+ if (sender.tag == 1) {
195
+ [self.input emitCustomKey];
196
+ return;
197
+ }
198
+
199
+ [self.input emitKeyPress:key];
200
+
201
+ NSString *text = self.input.getText ?: @"";
202
+ BOOL isEmpty = (text.length == 0);
203
+ BOOL isJustZero = [text isEqualToString:@"0"];
204
+
205
+ BOOL endsWithPlus = [text hasSuffix:@" + "];
206
+ BOOL endsWithMinus = [text hasSuffix:@" - "];
207
+ BOOL endsWithMul = [text hasSuffix:@" × "];
208
+ BOOL endsWithDiv = [text hasSuffix:@" ÷ "];
209
+ BOOL endsWithOperator = (endsWithPlus || endsWithMinus || endsWithMul || endsWithDiv);
210
+
211
+ BOOL endsWithSingleZeroAfterOp = [text hasSuffix:@" 0"];
212
+
213
+ BOOL (^isOpKey)(NSString *) = ^BOOL(NSString *k) {
214
+ return [k isEqualToString:@"+"] || [k isEqualToString:@"-"] ||
215
+ [k isEqualToString:@"×"] || [k isEqualToString:@"÷"];
216
+ };
217
+ void (^insert)(NSString *) = ^(NSString *s) { [self.input keyDidPress:s]; };
218
+ void (^replaceTrailingZeroWith)(NSString *) = ^(NSString *s) {
219
+ [self.input onBackSpace];
220
+ [self.input keyDidPress:s];
221
+ };
222
+ void (^replaceAllWith)(NSString *) = ^(NSString *s) {
223
+ [self.input clearText];
224
+ [self.input keyDidPress:s];
225
+ };
226
+
227
+ if ([key isEqualToString:@"AC"]) {
228
+ [self.input clearText];
229
+ return;
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
+ }
241
+
242
+ if (isOpKey(key)) {
243
+ if (!isEmpty) {
244
+ insert([NSString stringWithFormat:@" %@ ", key]);
245
+ }
246
+ return;
247
+ }
248
+
249
+ if ([key isEqualToString:@"0"] || [key isEqualToString:@"000"]) {
250
+ if (isEmpty) return;
251
+
252
+ if ([key isEqualToString:@"000"] && endsWithOperator) {
253
+ insert(@"0");
254
+ return;
255
+ }
256
+
257
+ if (endsWithSingleZeroAfterOp || isJustZero) return;
258
+
259
+ insert(key);
260
+ return;
261
+ }
262
+
263
+ if (isJustZero) {
264
+ replaceAllWith(key);
265
+ } else if (endsWithSingleZeroAfterOp) {
266
+ replaceTrailingZeroWith(key);
267
+ } else {
268
+ insert(key);
269
+ }
270
+ }
271
+
272
+
273
+ @end
274
+
@@ -0,0 +1,11 @@
1
+ #import <React/RCTViewComponentView.h>
2
+ #import <UIKit/UIKit.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ @interface NativeInputCalculator : RCTViewComponentView
7
+
8
+ @end
9
+
10
+ NS_ASSUME_NONNULL_END
11
+