@momo-kits/calculator-keyboard 0.150.2-beta.22 → 0.150.2-beta.23

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/README.md CHANGED
@@ -10,15 +10,57 @@ npm install react-native-calculator-keyboard
10
10
 
11
11
  ## Usage
12
12
 
13
-
14
13
  ```js
15
- import { CalculatorKeyboardView } from "react-native-calculator-keyboard";
14
+ import InputCalculator from '@momo-kits/calculator-keyboard';
16
15
 
17
16
  // ...
18
17
 
19
- <CalculatorKeyboardView color="tomato" />
18
+ <InputCalculator
19
+ mode="NumDefault"
20
+ customKeyText="Next"
21
+ onCustomKeyEvent={() => console.log('Custom key pressed')}
22
+ />;
23
+ ```
24
+
25
+ ## Requirements
26
+
27
+ **React Native 0.80+** with **Fabric (New Architecture) enabled**.
28
+
29
+ This library is **pure Fabric** implementation with:
30
+
31
+ - ✅ Zero RCTBridge dependencies
32
+ - ✅ Native C++ ComponentView on iOS
33
+ - ✅ Fabric ViewManager with codegen delegates on Android
34
+ - ✅ All Props, Events, Commands auto-generated by codegen
35
+ - ❌ No Paper (old architecture) support
36
+
37
+ ### Android Setup
38
+
39
+ Add to your `gradle.properties`:
40
+
41
+ ```properties
42
+ newArchEnabled=true
43
+ ```
44
+
45
+ Then rebuild:
46
+
47
+ ```bash
48
+ cd android && ./gradlew clean && cd ..
49
+ npx react-native run-android
50
+ ```
51
+
52
+ ### iOS Setup
53
+
54
+ **Required**: Set the environment variable before installing pods:
55
+
56
+ ```bash
57
+ cd ios
58
+ RCT_NEW_ARCH_ENABLED=1 pod install
59
+ cd ..
60
+ npx react-native run-ios
20
61
  ```
21
62
 
63
+ **Note**: This library uses Fabric ComponentView (`.mm` files) and will not work without `RCT_NEW_ARCH_ENABLED=1`.
22
64
 
23
65
  ## Contributing
24
66
 
@@ -12,6 +12,6 @@ class CalculatorKeyboardPackage : ReactPackage {
12
12
  }
13
13
 
14
14
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
- return listOf(RCTInputCalculator())
15
+ return listOf(InputCalculatorViewManager())
16
16
  }
17
17
  }
@@ -1,19 +1,21 @@
1
1
  package com.calculatorkeyboard
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.content.Context
4
5
  import android.content.res.ColorStateList
5
6
  import android.graphics.Color
6
7
  import android.graphics.drawable.GradientDrawable
7
8
  import android.view.Gravity
8
9
  import android.widget.Button
9
10
  import android.widget.ImageButton
10
- import androidx.appcompat.app.AppCompatActivity
11
11
  import androidx.constraintlayout.widget.ConstraintLayout
12
12
  import com.facebook.react.uimanager.ThemedReactContext
13
13
  import org.mariuszgromada.math.mxparser.Expression
14
14
  import androidx.core.graphics.toColorInt
15
- import com.calculatorkeyboard.RCTInputCalculator.Companion.calculatorHeight
15
+ import com.calculatorkeyboard.InputCalculatorViewManager.Companion.calculatorHeight
16
16
  import com.facebook.react.bridge.Arguments
17
+ import com.facebook.react.bridge.ReactContext
18
+ import com.facebook.react.uimanager.UIManagerHelper
17
19
  import com.facebook.react.uimanager.events.RCTEventEmitter
18
20
 
19
21
  @SuppressLint("SetTextI18n", "ViewConstructor")
@@ -21,53 +23,57 @@ class CustomKeyboardView(
21
23
  context: ThemedReactContext,
22
24
  private val editText: CalculatorEditText
23
25
  ) : ConstraintLayout(context) {
24
- private val keys = listOf(
26
+ private val numWithCTAKeys = listOf(
25
27
  listOf("1", "2", "3", "÷", "back"),
26
28
  listOf("4", "5", "6", "×", "="),
27
- listOf("7", "8", "9", "-", "Xong"),
29
+ listOf("7", "8", "9", "-", "Tiếp"),
28
30
  listOf("000", "0", "+")
29
31
  )
30
- private val specialKeys = listOf("=", "-", "×", "÷", "back", "+")
32
+ private val defaultKeys = listOf(
33
+ listOf("1", "2", "3", "÷", "AC"),
34
+ listOf("4", "5", "6", "×", "back"),
35
+ listOf("7", "8", "9", "-", "="),
36
+ listOf("000", "0", "+")
37
+ )
38
+ private val specialKeys = listOf("=", "-", "×", "÷", "back", "+", "AC")
31
39
  private val separatorWidth = 8f
32
40
  private var specialButtonColor: Int = "#D8D8D8".toColorInt()
33
41
 
42
+ private var keyboardMode: String = "NumDefault"
43
+
34
44
  private var customKeyButton: Button? = null
35
45
  private var customKeyButtonBackground: Int = "#D8D8D8".toColorInt()
36
46
  private var customKeyButtonTextColor: Int = Color.BLACK
37
47
  private var customKeyButtonState: String = "default"
38
48
 
39
49
  init {
40
- val activity = context.currentActivity as? AppCompatActivity
41
- if (activity != null) {
42
- val displayMetrics = resources.displayMetrics
43
- val widthButton = (displayMetrics.widthPixels - separatorWidth * 2 - 4 * separatorWidth) / 5f
44
- val heightButton = (calculatorHeight - separatorWidth * 2 - 3 * separatorWidth) / 4
45
-
46
50
  isClickable = false
47
51
  isFocusable = false
48
52
  isFocusableInTouchMode = false
49
53
  clipToPadding = false
50
54
  clipChildren = false
51
-
52
- renderUI(widthButton, heightButton)
53
- }
54
-
55
55
  }
56
56
 
57
- private fun renderUI(buttonWidth: Float, buttonHeight: Float) {
57
+ private fun renderUI() {
58
+ val displayMetrics = resources.displayMetrics
59
+ val buttonWidth = (displayMetrics.widthPixels - separatorWidth * 2 - 4 * separatorWidth) / 5f
60
+ val buttonHeight = (calculatorHeight - separatorWidth * 2 - 3 * separatorWidth) / 4
61
+
58
62
  var yOffset = separatorWidth
63
+ val keys = if (keyboardMode == "NumWithCTA") numWithCTAKeys else defaultKeys
59
64
  for ((rowIndex, row) in keys.withIndex()) {
60
65
  var xOffset = separatorWidth
61
66
  for ((colIndex, key) in row.withIndex()) {
62
- val isCustomKey = rowIndex == 2 && colIndex == 4
67
+ val isMainKey = rowIndex == 2 && colIndex == 4
68
+ val isMainCTAKey = isMainKey && keyboardMode == "NumWithCTA"
63
69
  val width = if (key == "000") buttonWidth * 2 + separatorWidth else buttonWidth
64
- val height = if (isCustomKey) buttonHeight * 2 + separatorWidth else buttonHeight
70
+ val height = if (isMainKey) buttonHeight * 2 + separatorWidth else buttonHeight
65
71
 
66
72
  val button = if (key == "back") {
67
73
  createImageButton(key, xOffset, yOffset, buttonWidth.toInt(), buttonHeight.toInt())
68
74
  } else {
69
- createButton(key, xOffset, yOffset, width.toInt(), height.toInt(), isCustomKey).also { b ->
70
- if (isCustomKey) customKeyButton = b
75
+ createButton(key, xOffset, yOffset, width.toInt(), height.toInt(), isMainKey, isMainCTAKey).also { b ->
76
+ if (isMainCTAKey) customKeyButton = b
71
77
  }
72
78
  }
73
79
 
@@ -85,7 +91,8 @@ class CustomKeyboardView(
85
91
  yOffset: Float,
86
92
  buttonWidth: Int,
87
93
  buttonHeight: Int,
88
- isCustomKey: Boolean
94
+ isMainKey: Boolean,
95
+ isMainCTAKey: Boolean
89
96
  ): Button {
90
97
  return Button(context).apply {
91
98
  val shapeInit = GradientDrawable().apply {
@@ -98,7 +105,7 @@ class CustomKeyboardView(
98
105
  background = shapeInit
99
106
  text = key
100
107
  setTypeface(typeface)
101
- textSize = (if (isCustomKey) 18 else 24).toFloat()
108
+ textSize = (if (isMainCTAKey) 18 else 24).toFloat()
102
109
  setTextColor(Color.BLACK)
103
110
  stateListAnimator = null
104
111
  maxLines = 1
@@ -110,7 +117,7 @@ class CustomKeyboardView(
110
117
  constrainedWidth = false
111
118
  }
112
119
 
113
- if (specialKeys.contains(key)) {
120
+ if (specialKeys.contains(key) || isMainKey) {
114
121
  background = GradientDrawable().apply {
115
122
  shape = GradientDrawable.RECTANGLE
116
123
  cornerRadius = 24f
@@ -125,7 +132,7 @@ class CustomKeyboardView(
125
132
 
126
133
  translationX = xOffset.toInt().toFloat()
127
134
  translationY = yOffset.toInt().toFloat()
128
- setOnClickListener { onKeyPress(key, isCustomKey) }
135
+ setOnClickListener { onKeyPress(key, isMainCTAKey) }
129
136
  }
130
137
  }
131
138
 
@@ -163,46 +170,15 @@ class CustomKeyboardView(
163
170
  }
164
171
  }
165
172
 
166
- fun updateButtonColors(color: Int) {
167
- specialButtonColor = color
168
- for (i in 0 until childCount) {
169
- val child = getChildAt(i)
170
- if (child is Button) {
171
- val key = child.text.toString()
172
- if (specialKeys.contains(key)) {
173
- if (key == "=") {
174
- child.background = GradientDrawable().apply {
175
- shape = GradientDrawable.RECTANGLE
176
- cornerRadius = 24f
177
- setColor(specialButtonColor)
178
- }
179
- } else {
180
- child.background = GradientDrawable().apply {
181
- shape = GradientDrawable.RECTANGLE
182
- cornerRadius = 24f
183
- setColor(specialButtonColor)
184
- }
185
- }
186
- child.setTextColor(Color.BLACK)
187
- }
188
- } else if (child is ImageButton) {
189
- child.background = GradientDrawable().apply {
190
- shape = GradientDrawable.RECTANGLE
191
- cornerRadius = 24f
192
- setColor(specialButtonColor)
193
- }
194
- }
195
- }
196
- }
197
-
198
- private fun onKeyPress(key: String, isCustomKey: Boolean) {
199
- if (isCustomKey) {
200
- emitCustomKey()
173
+ private fun onKeyPress(key: String, isMainCTAKey: Boolean) {
174
+ if (isMainCTAKey) {
175
+ emitCustomKey(context)
201
176
  return
202
177
  }
203
178
 
204
- emitKeyPress(key)
179
+ emitKeyPress(context, key)
205
180
  when (key) {
181
+ "AC" -> clearText()
206
182
  "back" -> onBackSpace()
207
183
  "=" -> calculateResult()
208
184
  "×", "+", "-", "÷" -> keyDidPress(" $key ")
@@ -215,6 +191,10 @@ class CustomKeyboardView(
215
191
  editText.text?.replace(editText.selectionStart, editText.selectionEnd, key)
216
192
  }
217
193
 
194
+ private fun clearText() {
195
+ editText.text?.clear()
196
+ }
197
+
218
198
  private fun onBackSpace() {
219
199
  val start = editText.selectionStart
220
200
  val end = editText.selectionEnd
@@ -251,44 +231,56 @@ class CustomKeyboardView(
251
231
  }
252
232
  }
253
233
 
254
- private fun emitKeyPress(key: String) {
255
- val reactContext = context as ThemedReactContext
256
- val params = Arguments.createMap().apply {
257
- putString("key", key)
258
- }
259
- reactContext.getJSModule(RCTEventEmitter::class.java)
260
- .receiveEvent(editText.id, "onKeyPress", params)
234
+ private fun emitKeyPress(context: Context, key: String) {
235
+ val reactContext = context as ReactContext
236
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
237
+ val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.id)
238
+ val payload =
239
+ Arguments.createMap().apply {
240
+ putString("key", key)
241
+ }
242
+ val event = OnKeyPressEvent(surfaceId, editText.id, payload)
243
+
244
+ eventDispatcher?.dispatchEvent(event)
261
245
  }
262
246
 
263
- private fun emitCustomKey() {
264
- val reactContext = context as ThemedReactContext
265
- reactContext.getJSModule(RCTEventEmitter::class.java)
266
- .receiveEvent(editText.id, "onCustomKeyEvent", null)
247
+ private fun emitCustomKey(context: Context) {
248
+ val reactContext = context as ReactContext
249
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
250
+ val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.id)
251
+
252
+ val event = OnCustomKeyPressEvent(surfaceId, editText.id)
253
+
254
+ eventDispatcher?.dispatchEvent(event)
267
255
  }
268
256
 
269
257
  fun setCustomKeyText(text: String) {
270
258
  customKeyButton?.text = text
271
259
  }
272
260
 
261
+ fun setMode(mode: String) {
262
+ keyboardMode = mode
263
+ renderUI()
264
+ }
265
+
273
266
  fun setCustomKeyBackground(background: Int) {
274
267
  customKeyButtonBackground = background
275
- updateCustomKeyUI(background, customKeyButtonTextColor, customKeyButtonState)
268
+ updateCustomKeyUI(background, customKeyButtonTextColor)
276
269
  }
277
270
 
278
271
  fun setCustomKeyTextColor(textColor: Int) {
279
272
  customKeyButtonTextColor = textColor
280
- updateCustomKeyUI(customKeyButtonBackground, textColor, customKeyButtonState)
273
+ updateCustomKeyUI(customKeyButtonBackground, textColor)
281
274
  }
282
275
 
283
276
 
284
277
  fun setCustomKeyState(state: String) {
285
278
  customKeyButtonState = state
286
279
  customKeyButton?.isEnabled = state != "disable"
287
- updateCustomKeyUI(customKeyButtonBackground, customKeyButtonTextColor, state)
280
+ updateCustomKeyUI(customKeyButtonBackground, customKeyButtonTextColor)
288
281
  }
289
282
 
290
- private fun updateCustomKeyUI(background: Int, textColor: Int, state: String){
291
-
283
+ private fun updateCustomKeyUI(background: Int, textColor: Int){
292
284
  customKeyButton?.background = GradientDrawable().apply {
293
285
  shape = GradientDrawable.RECTANGLE
294
286
  cornerRadius = 24f
@@ -297,5 +289,4 @@ class CustomKeyboardView(
297
289
  customKeyButton?.setTextColor(textColor)
298
290
  }
299
291
 
300
-
301
292
  }
@@ -0,0 +1,36 @@
1
+ package com.calculatorkeyboard
2
+
3
+ import com.facebook.react.bridge.WritableMap
4
+ import com.facebook.react.uimanager.events.Event
5
+
6
+ class OnChangeEvent(
7
+ surfaceId: Int,
8
+ viewId: Int,
9
+ private val payload: WritableMap
10
+ ) : Event<OnChangeEvent>(surfaceId, viewId) {
11
+ override fun getEventName() = "onChange"
12
+
13
+ override fun getEventData() = payload
14
+ }
15
+
16
+ class OnKeyPressEvent(
17
+ surfaceId: Int,
18
+ viewId: Int,
19
+ private val payload: WritableMap
20
+ ) : Event<OnChangeEvent>(surfaceId, viewId) {
21
+ override fun getEventName() = "onKeyPress"
22
+
23
+ override fun getEventData() = payload
24
+ }
25
+
26
+ class OnCustomKeyPressEvent(
27
+ surfaceId: Int,
28
+ viewId: Int
29
+ ) : Event<OnChangeEvent>(surfaceId, viewId) {
30
+ override fun getEventName() = "onCustomKeyEvent"
31
+
32
+ override fun getEventData() = null
33
+ }
34
+
35
+
36
+
@@ -3,20 +3,43 @@ 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.provider.Settings.Global.putString
9
+ import android.text.Editable
10
+ import android.text.TextWatcher
6
11
  import android.view.KeyEvent
7
12
  import android.view.inputmethod.InputMethodManager
8
13
  import androidx.core.graphics.toColorInt
9
14
  import androidx.core.view.ViewCompat
10
15
  import androidx.core.view.WindowInsetsCompat
16
+ import androidx.core.widget.addTextChangedListener
17
+ import com.facebook.react.bridge.Arguments
18
+ import com.facebook.react.bridge.ReactContext
11
19
  import com.facebook.react.bridge.ReadableArray
20
+ import com.facebook.react.bridge.ReadableMap
12
21
  import com.facebook.react.bridge.UiThreadUtil
22
+ import com.facebook.react.module.annotations.ReactModule
13
23
  import com.facebook.react.uimanager.PixelUtil.dpToPx
24
+ import com.facebook.react.uimanager.SimpleViewManager
14
25
  import com.facebook.react.uimanager.ThemedReactContext
26
+ import com.facebook.react.uimanager.UIManagerHelper
27
+ import com.facebook.react.uimanager.ViewManagerDelegate
15
28
  import com.facebook.react.uimanager.annotations.ReactProp
29
+ import com.facebook.react.uimanager.events.RCTEventEmitter
30
+ import com.facebook.react.viewmanagers.NativeInputCalculatorManagerDelegate
31
+ import com.facebook.react.viewmanagers.NativeInputCalculatorManagerInterface
16
32
  import com.facebook.react.views.textinput.ReactEditText
17
33
  import com.facebook.react.views.textinput.ReactTextInputManager
18
34
 
19
- class RCTInputCalculator : ReactTextInputManager() {
35
+ @ReactModule(name = InputCalculatorViewManager.REACT_CLASS)
36
+ class InputCalculatorViewManager : SimpleViewManager<ReactEditText>(), NativeInputCalculatorManagerInterface<ReactEditText> {
37
+ private val delegate: NativeInputCalculatorManagerDelegate<ReactEditText, InputCalculatorViewManager> =
38
+ NativeInputCalculatorManagerDelegate(this)
39
+
40
+ override fun getDelegate(): ViewManagerDelegate<ReactEditText> = delegate
41
+
42
+ override fun getName() = REACT_CLASS
20
43
 
21
44
  private var keyboardView: CustomKeyboardView? = null
22
45
  private lateinit var editText: CalculatorEditText
@@ -27,15 +50,14 @@ class RCTInputCalculator : ReactTextInputManager() {
27
50
  private var backListenerAttached = false
28
51
  private var overlayShowing = false
29
52
 
30
- override fun getName() = REACT_CLASS
31
53
 
32
54
  companion object {
33
- const val REACT_CLASS = "RCTInputCalculator"
55
+ const val REACT_CLASS = "NativeInputCalculator"
34
56
  val calculatorHeight: Int = 240.dpToPx().toInt()
35
57
  }
36
58
 
37
59
  @ReactProp(name = "value")
38
- fun setValue(view: ReactEditText, value: String?) {
60
+ override fun setValue(view: ReactEditText, value: String?) {
39
61
  UiThreadUtil.runOnUiThread {
40
62
  val e = view.editableText ?: run { view.setText(value ?: ""); return@runOnUiThread }
41
63
  val newText = value ?: ""
@@ -48,29 +70,72 @@ class RCTInputCalculator : ReactTextInputManager() {
48
70
  }
49
71
  }
50
72
 
73
+ override fun setTextAttributes(view: ReactEditText?, value: ReadableMap?) {
74
+ val fontWeightStr = value?.getString("fontWeight")
75
+ val fontSize = value?.getDouble("fontSize")
76
+
77
+ fontWeightStr?.let { weightStr ->
78
+ val weight = when (weightStr) {
79
+ "100" -> 100
80
+ "200" -> 200
81
+ "300" -> 300
82
+ "400", "normal" -> 400
83
+ "500" -> 500
84
+ "600" -> 600
85
+ "700", "bold" -> 700
86
+ "800" -> 800
87
+ "900" -> 900
88
+ else -> 400
89
+ }
90
+
91
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
92
+ view?.typeface = Typeface.create(view.typeface, weight, false)
93
+ } else {
94
+ view?.typeface = if (weight >= 600) {
95
+ Typeface.create(view.typeface, Typeface.BOLD)
96
+ } else {
97
+ Typeface.create(view.typeface, Typeface.NORMAL)
98
+ }
99
+ }
100
+ }
101
+
102
+ fontSize?.let {
103
+ view?.textSize = it.toFloat()
104
+ }
105
+ }
106
+
107
+
108
+ @ReactProp(name = "mode")
109
+ override fun setMode(view: ReactEditText, mode: String?) {
110
+ keyboardView?.setMode(mode ?: "NumDefault")
111
+ }
112
+
51
113
  @ReactProp(name = "customKeyText")
52
- fun setCustomKeyText(view: ReactEditText, text: String?) {
53
- keyboardView?.setCustomKeyText(text ?: "Xong")
114
+ override fun setCustomKeyText(view: ReactEditText, text: String?) {
115
+ keyboardView?.setCustomKeyText(text ?: "Tiếp")
54
116
  }
55
117
 
56
118
  @ReactProp(name = "customKeyBackground")
57
- fun setCustomKeyBackground(view: ReactEditText, background: String?) {
119
+ override fun setCustomKeyBackground(view: ReactEditText, background: String?) {
58
120
  keyboardView?.setCustomKeyBackground((background ?: "#d8d8d8").toColorInt())
59
121
  }
60
122
 
61
123
  @ReactProp(name = "customKeyTextColor")
62
- fun setCustomKeyTextColor(view: ReactEditText, textColor: String?) {
124
+ override fun setCustomKeyTextColor(view: ReactEditText, textColor: String?) {
63
125
  keyboardView?.setCustomKeyTextColor(textColor?.toColorInt() ?: Color.BLACK)
64
126
  }
65
127
 
66
128
  @ReactProp(name = "customKeyState")
67
- fun setCustomKeyState(view: ReactEditText, state: String?) {
129
+ override fun setCustomKeyState(view: ReactEditText, state: String?) {
68
130
  keyboardView?.setCustomKeyState(state ?: "default")
69
131
  }
70
132
 
71
- @ReactProp(name = "keyboardColor")
72
- fun setKeyboardColor(view: ReactEditText, color: String) {
73
- keyboardView?.updateButtonColors(color.toColorInt())
133
+ override fun focus(view: ReactEditText?) {
134
+ UiThreadUtil.runOnUiThread { if (!editText.isFocused) editText.requestFocus() }
135
+ }
136
+
137
+ override fun blur(view: ReactEditText?) {
138
+ UiThreadUtil.runOnUiThread { if (editText.isFocused) editText.clearFocus() }
74
139
  }
75
140
 
76
141
  @SuppressLint("ClickableViewAccessibility")
@@ -101,6 +166,16 @@ class RCTInputCalculator : ReactTextInputManager() {
101
166
  }
102
167
  false
103
168
  }
169
+ addTextChangedListener(object : TextWatcher{
170
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
171
+
172
+ override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
173
+
174
+ override fun afterTextChanged(s: Editable?) {
175
+ emitOnChange(context, s.toString())
176
+ }
177
+
178
+ })
104
179
  }
105
180
 
106
181
  keyboardView = CustomKeyboardView(context, editText).apply {
@@ -165,33 +240,31 @@ class RCTInputCalculator : ReactTextInputManager() {
165
240
  v.showSoftInputOnFocus = true
166
241
  }
167
242
 
168
- override fun getCommandsMap(): Map<String, Int> = mapOf("blur" to 1, "focus" to 2)
243
+ private fun emitOnChange(context: Context, text: String) {
244
+ val reactContext = context as ReactContext
245
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
246
+ val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.id)
247
+ val payload =
248
+ Arguments.createMap().apply {
249
+ putString("text", text)
250
+ }
251
+ val event = OnChangeEvent(surfaceId, editText.id, payload)
169
252
 
170
- override fun receiveCommand(reactEditText: ReactEditText, commandId: Int, args: ReadableArray?) {
171
- when (commandId) {
172
- 1 -> blur()
173
- 2 -> focus()
174
- }
253
+ eventDispatcher?.dispatchEvent(event)
175
254
  }
176
255
 
177
256
  override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> {
178
- val base = super.getExportedCustomBubblingEventTypeConstants().toMutableMap()
257
+ val base = super.getExportedCustomBubblingEventTypeConstants()?.toMutableMap() ?: mutableMapOf()
179
258
  base["onKeyPress"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onKeyPress"))
259
+ base["onChange"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onChange"))
180
260
  return base
181
261
  }
182
262
 
183
263
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
184
- val base = super.getExportedCustomDirectEventTypeConstants().toMutableMap()
264
+ val base = super.getExportedCustomDirectEventTypeConstants()?.toMutableMap() ?: mutableMapOf()
185
265
  base["onCustomKeyEvent"] = mapOf("registrationName" to "onCustomKeyEvent")
186
266
  return base
187
267
  }
188
268
 
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
269
  }
197
270
 
@@ -0,0 +1,30 @@
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
+ - (void)onBackSpace;
10
+ - (void)calculateResult;
11
+ - (void)emitCustomKey;
12
+ - (void)emitKeyPress:(NSString *)key;
13
+
14
+ @end
15
+
16
+ @interface CalculatorKeyboardView : UIView
17
+
18
+ @property (nonatomic, weak, nullable) id<CalculatorKeyboardInput> input;
19
+ @property (nonatomic, strong, nullable) NSString *keyboardMode;
20
+ @property (nonatomic, strong, nullable) NSString *customKeyText;
21
+ @property (nonatomic, strong, nullable) NSString *customKeyBackground;
22
+ @property (nonatomic, strong, nullable) NSString *customKeyTextColor;
23
+ @property (nonatomic, strong, nullable) NSString *customKeyState;
24
+
25
+ - (void)setKeyboardColor:(UIColor *)color;
26
+
27
+ @end
28
+
29
+ NS_ASSUME_NONNULL_END
30
+