@momo-kits/calculator-keyboard 0.150.2-beta.2 → 0.150.2-beta.20
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 +99 -40
- package/android/src/main/java/com/calculatorkeyboard/KeyboardOverplayHost.kt +232 -0
- package/android/src/main/java/com/calculatorkeyboard/RCTInputCalculator.kt +112 -94
- package/ios/CalculatorKeyboardView.swift +53 -15
- package/ios/InputCalculator.m +6 -0
- package/ios/InputCalculator.swift +30 -10
- package/package.json +7 -131
- package/src/index.tsx +60 -15
- package/lib/commonjs/index.js +0 -48
- package/lib/commonjs/index.js.map +0 -1
- package/lib/module/index.js +0 -44
- package/lib/module/index.js.map +0 -1
- package/lib/typescript/commonjs/package.json +0 -1
- package/lib/typescript/commonjs/src/index.d.ts +0 -13
- package/lib/typescript/commonjs/src/index.d.ts.map +0 -1
- package/lib/typescript/module/package.json +0 -1
- package/lib/typescript/module/src/index.d.ts +0 -13
- package/lib/typescript/module/src/index.d.ts.map +0 -1
|
@@ -1,41 +1,37 @@
|
|
|
1
1
|
package com.calculatorkeyboard
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
-
import android.
|
|
5
|
-
import android.graphics.
|
|
6
|
-
import android.graphics.drawable.ColorDrawable
|
|
7
|
-
import android.view.Gravity
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.graphics.Color
|
|
8
6
|
import android.view.KeyEvent
|
|
9
|
-
import android.view.
|
|
10
|
-
import android.view.WindowInsets
|
|
11
|
-
import android.view.WindowManager
|
|
12
|
-
import android.widget.PopupWindow
|
|
13
|
-
import androidx.constraintlayout.widget.ConstraintLayout
|
|
7
|
+
import android.view.inputmethod.InputMethodManager
|
|
14
8
|
import androidx.core.graphics.toColorInt
|
|
9
|
+
import androidx.core.view.ViewCompat
|
|
10
|
+
import androidx.core.view.WindowInsetsCompat
|
|
15
11
|
import com.facebook.react.bridge.ReadableArray
|
|
16
12
|
import com.facebook.react.bridge.UiThreadUtil
|
|
13
|
+
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
17
14
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
18
15
|
import com.facebook.react.uimanager.annotations.ReactProp
|
|
19
16
|
import com.facebook.react.views.textinput.ReactEditText
|
|
20
17
|
import com.facebook.react.views.textinput.ReactTextInputManager
|
|
21
|
-
import androidx.core.graphics.drawable.toDrawable
|
|
22
|
-
import androidx.core.view.ViewCompat
|
|
23
|
-
import androidx.core.view.WindowInsetsCompat
|
|
24
|
-
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
25
18
|
|
|
26
19
|
class RCTInputCalculator : ReactTextInputManager() {
|
|
27
20
|
|
|
28
21
|
private var keyboardView: CustomKeyboardView? = null
|
|
29
|
-
private var calculatorHeight: Int = 290.dpToPx().toInt()
|
|
30
|
-
private var popup: PopupWindow? = null
|
|
31
|
-
private val animationDuration = 250L
|
|
32
|
-
|
|
33
22
|
private lateinit var editText: CalculatorEditText
|
|
23
|
+
private lateinit var imm: InputMethodManager
|
|
24
|
+
|
|
25
|
+
private val overlayHost = KeyboardOverlayHost()
|
|
26
|
+
|
|
27
|
+
private var backListenerAttached = false
|
|
28
|
+
private var overlayShowing = false
|
|
34
29
|
|
|
35
30
|
override fun getName() = REACT_CLASS
|
|
36
31
|
|
|
37
32
|
companion object {
|
|
38
33
|
const val REACT_CLASS = "RCTInputCalculator"
|
|
34
|
+
val calculatorHeight: Int = 240.dpToPx().toInt()
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
@ReactProp(name = "value")
|
|
@@ -47,15 +43,31 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
47
43
|
|
|
48
44
|
val wasFocused = view.hasFocus()
|
|
49
45
|
val atEnd = wasFocused && view.selectionStart == e.length && view.selectionEnd == e.length
|
|
50
|
-
|
|
51
46
|
e.replace(0, e.length, newText)
|
|
52
|
-
|
|
53
|
-
if (!wasFocused || atEnd) {
|
|
54
|
-
view.setSelection(newText.length)
|
|
55
|
-
}
|
|
47
|
+
if (!wasFocused || atEnd) view.setSelection(newText.length)
|
|
56
48
|
}
|
|
57
49
|
}
|
|
58
50
|
|
|
51
|
+
@ReactProp(name = "customKeyText")
|
|
52
|
+
fun setCustomKeyText(view: ReactEditText, text: String?) {
|
|
53
|
+
keyboardView?.setCustomKeyText(text ?: "Xong")
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@ReactProp(name = "customKeyBackground")
|
|
57
|
+
fun setCustomKeyBackground(view: ReactEditText, background: String?) {
|
|
58
|
+
keyboardView?.setCustomKeyBackground((background ?: "#d8d8d8").toColorInt())
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@ReactProp(name = "customKeyTextColor")
|
|
62
|
+
fun setCustomKeyTextColor(view: ReactEditText, textColor: String?) {
|
|
63
|
+
keyboardView?.setCustomKeyTextColor(textColor?.toColorInt() ?: Color.BLACK)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@ReactProp(name = "customKeyState")
|
|
67
|
+
fun setCustomKeyState(view: ReactEditText, state: String?) {
|
|
68
|
+
keyboardView?.setCustomKeyState(state ?: "default")
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
@ReactProp(name = "keyboardColor")
|
|
60
72
|
fun setKeyboardColor(view: ReactEditText, color: String) {
|
|
61
73
|
keyboardView?.updateButtonColors(color.toColorInt())
|
|
@@ -63,8 +75,32 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
63
75
|
|
|
64
76
|
@SuppressLint("ClickableViewAccessibility")
|
|
65
77
|
override fun createViewInstance(context: ThemedReactContext): ReactEditText {
|
|
78
|
+
imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
79
|
+
|
|
66
80
|
editText = CalculatorEditText(context).apply {
|
|
67
81
|
showSoftInputOnFocus = false
|
|
82
|
+
isFocusableInTouchMode = true
|
|
83
|
+
setOnTouchListener { v, event ->
|
|
84
|
+
if (event.action == android.view.MotionEvent.ACTION_DOWN) {
|
|
85
|
+
showSoftInputOnFocus = false
|
|
86
|
+
ViewCompat.getWindowInsetsController(this)?.hide(WindowInsetsCompat.Type.ime())
|
|
87
|
+
imm.hideSoftInputFromWindow(windowToken, 0)
|
|
88
|
+
|
|
89
|
+
if (!isFocused) requestFocus()
|
|
90
|
+
|
|
91
|
+
val kb = keyboardView
|
|
92
|
+
if (kb != null && !overlayShowing) {
|
|
93
|
+
overlayHost.show(
|
|
94
|
+
anchorView = this,
|
|
95
|
+
keyboardView = kb,
|
|
96
|
+
heightPx = calculatorHeight
|
|
97
|
+
)
|
|
98
|
+
overlayShowing = true
|
|
99
|
+
}
|
|
100
|
+
return@setOnTouchListener true
|
|
101
|
+
}
|
|
102
|
+
false
|
|
103
|
+
}
|
|
68
104
|
}
|
|
69
105
|
|
|
70
106
|
keyboardView = CustomKeyboardView(context, editText).apply {
|
|
@@ -72,19 +108,34 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
72
108
|
elevation = 24f
|
|
73
109
|
}
|
|
74
110
|
|
|
111
|
+
if (!backListenerAttached) {
|
|
112
|
+
editText.setOnKeyListener { v, keyCode, event ->
|
|
113
|
+
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP && v.hasFocus()) {
|
|
114
|
+
v.clearFocus()
|
|
115
|
+
true
|
|
116
|
+
} else false
|
|
117
|
+
}
|
|
118
|
+
backListenerAttached = true
|
|
119
|
+
}
|
|
120
|
+
|
|
75
121
|
editText.onFocusListener = object : CalculatorEditText.OnFocusChangeListener {
|
|
76
122
|
override fun onFocusChange(view: CalculatorEditText, hasFocus: Boolean) {
|
|
77
123
|
UiThreadUtil.runOnUiThread {
|
|
78
124
|
if (hasFocus) {
|
|
79
|
-
|
|
125
|
+
disableSystemImeFor(view)
|
|
126
|
+
if (!overlayShowing) {
|
|
127
|
+
val kb = keyboardView ?: return@runOnUiThread
|
|
128
|
+
overlayHost.show(
|
|
129
|
+
anchorView = view,
|
|
130
|
+
keyboardView = kb,
|
|
131
|
+
heightPx = calculatorHeight
|
|
132
|
+
)
|
|
133
|
+
overlayShowing = true
|
|
134
|
+
}
|
|
80
135
|
} else {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (keyCode == KeyEvent.KEYCODE_BACK && hasFocus) {
|
|
85
|
-
v.clearFocus()
|
|
86
|
-
true
|
|
87
|
-
} else false
|
|
136
|
+
overlayHost.hide()
|
|
137
|
+
overlayShowing = false
|
|
138
|
+
enableSystemImeFor(view)
|
|
88
139
|
}
|
|
89
140
|
}
|
|
90
141
|
}
|
|
@@ -93,87 +144,54 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
93
144
|
return editText
|
|
94
145
|
}
|
|
95
146
|
|
|
96
|
-
override fun getCommandsMap(): Map<String, Int> {
|
|
97
|
-
return mapOf(
|
|
98
|
-
"blur" to 1,
|
|
99
|
-
"focus" to 2
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
147
|
|
|
103
|
-
override fun
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
148
|
+
override fun onDropViewInstance(view: ReactEditText) {
|
|
149
|
+
super.onDropViewInstance(view)
|
|
150
|
+
overlayHost.hide()
|
|
151
|
+
overlayHost.detach()
|
|
152
|
+
overlayShowing = false
|
|
153
|
+
|
|
108
154
|
}
|
|
109
155
|
|
|
110
|
-
private fun
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
popup = PopupWindow(
|
|
115
|
-
content,
|
|
116
|
-
WindowManager.LayoutParams.MATCH_PARENT,
|
|
117
|
-
calculatorHeight + bottomInsetFrom(editText.rootView),
|
|
118
|
-
false
|
|
119
|
-
).apply {
|
|
120
|
-
setBackgroundDrawable(android.graphics.Color.TRANSPARENT.toDrawable())
|
|
121
|
-
isOutsideTouchable = false
|
|
122
|
-
isClippingEnabled = false
|
|
123
|
-
softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
|
|
124
|
-
inputMethodMode = PopupWindow.INPUT_METHOD_NOT_NEEDED
|
|
156
|
+
private fun disableSystemImeFor(v: ReactEditText) {
|
|
157
|
+
v.showSoftInputOnFocus = false
|
|
158
|
+
if (android.os.Build.VERSION.SDK_INT >= 30) {
|
|
159
|
+
ViewCompat.getWindowInsetsController(v)?.hide(WindowInsetsCompat.Type.ime())
|
|
125
160
|
}
|
|
161
|
+
imm.hideSoftInputFromWindow(v.windowToken, 0)
|
|
126
162
|
}
|
|
127
163
|
|
|
128
|
-
private fun
|
|
129
|
-
|
|
130
|
-
val mask = WindowInsetsCompat.Type.navigationBars() or WindowInsetsCompat.Type.displayCutout()
|
|
131
|
-
return insets.getInsets(mask).bottom
|
|
164
|
+
private fun enableSystemImeFor(v: ReactEditText) {
|
|
165
|
+
v.showSoftInputOnFocus = true
|
|
132
166
|
}
|
|
133
167
|
|
|
134
|
-
|
|
135
|
-
ensurePopup()
|
|
136
|
-
val p = popup ?: return
|
|
137
|
-
if (p.isShowing) return
|
|
168
|
+
override fun getCommandsMap(): Map<String, Int> = mapOf("blur" to 1, "focus" to 2)
|
|
138
169
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
root.animate()
|
|
145
|
-
?.translationY(0f)
|
|
146
|
-
?.setDuration(animationDuration)
|
|
147
|
-
?.start()
|
|
170
|
+
override fun receiveCommand(reactEditText: ReactEditText, commandId: Int, args: ReadableArray?) {
|
|
171
|
+
when (commandId) {
|
|
172
|
+
1 -> blur()
|
|
173
|
+
2 -> focus()
|
|
174
|
+
}
|
|
148
175
|
}
|
|
149
176
|
|
|
150
|
-
|
|
151
|
-
val
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
root.animate()
|
|
156
|
-
.translationY(calculatorHeight.toFloat())
|
|
157
|
-
.setDuration(animationDuration)
|
|
158
|
-
.withEndAction {
|
|
159
|
-
try {
|
|
160
|
-
if (p.isShowing) p.dismiss()
|
|
161
|
-
} catch (_: Throwable) { }
|
|
162
|
-
}
|
|
163
|
-
.start()
|
|
177
|
+
override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> {
|
|
178
|
+
val base = super.getExportedCustomBubblingEventTypeConstants().toMutableMap()
|
|
179
|
+
base["onKeyPress"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onKeyPress"))
|
|
180
|
+
return base
|
|
181
|
+
}
|
|
164
182
|
|
|
165
|
-
|
|
183
|
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
|
|
184
|
+
val base = super.getExportedCustomDirectEventTypeConstants().toMutableMap()
|
|
185
|
+
base["onCustomKeyEvent"] = mapOf("registrationName" to "onCustomKeyEvent")
|
|
186
|
+
return base
|
|
166
187
|
}
|
|
167
188
|
|
|
168
189
|
private fun focus() {
|
|
169
|
-
UiThreadUtil.runOnUiThread {
|
|
170
|
-
if (!editText.isFocused) editText.requestFocus()
|
|
171
|
-
}
|
|
190
|
+
UiThreadUtil.runOnUiThread { if (!editText.isFocused) editText.requestFocus() }
|
|
172
191
|
}
|
|
173
192
|
|
|
174
193
|
private fun blur() {
|
|
175
|
-
UiThreadUtil.runOnUiThread {
|
|
176
|
-
if (editText.isFocused) editText.clearFocus()
|
|
177
|
-
}
|
|
194
|
+
UiThreadUtil.runOnUiThread { if (editText.isFocused) editText.clearFocus() }
|
|
178
195
|
}
|
|
179
196
|
}
|
|
197
|
+
|
|
@@ -8,14 +8,20 @@ class CalculatorKeyboardView: UIView {
|
|
|
8
8
|
weak var input: InputCalculator?
|
|
9
9
|
|
|
10
10
|
private let keys: [[String]] = [
|
|
11
|
-
["
|
|
12
|
-
["
|
|
13
|
-
["
|
|
14
|
-
["
|
|
15
|
-
["000", "0"]
|
|
11
|
+
["1", "2", "3", "÷", "back"],
|
|
12
|
+
["4", "5", "6", "×", "="],
|
|
13
|
+
["7", "8", "9", "-", "Xong"],
|
|
14
|
+
["000", "0", "+"],
|
|
16
15
|
]
|
|
17
16
|
private let SEPARATOR_WIDTH: CGFloat = 4
|
|
18
|
-
private let specialKeys: Set<String> = ["=", "-", "×", "÷", "
|
|
17
|
+
private let specialKeys: Set<String> = ["=", "-", "×", "÷", "back", "+"]
|
|
18
|
+
|
|
19
|
+
var customKeyText: String? { didSet { updateCustomKeyTitle() } }
|
|
20
|
+
var customKeyBackground: String? { didSet { updateCustomKeyBackground() } }
|
|
21
|
+
var customKeyTextColor: String? { didSet { updateCustomKeyBackground() } }
|
|
22
|
+
var customKeyState: String? { didSet { updateCustomKeyBackground() } }
|
|
23
|
+
private weak var customKeyButton: UIButton?
|
|
24
|
+
|
|
19
25
|
|
|
20
26
|
override init(frame: CGRect) {
|
|
21
27
|
super.init(frame: frame)
|
|
@@ -34,8 +40,8 @@ class CalculatorKeyboardView: UIView {
|
|
|
34
40
|
self.subviews.forEach { $0.removeFromSuperview() }
|
|
35
41
|
|
|
36
42
|
backgroundColor = UIColor(hex: "#f2f2f6")
|
|
37
|
-
let buttonWidth = (UIScreen.main.bounds.width - SEPARATOR_WIDTH * 2 -
|
|
38
|
-
let buttonHeight: CGFloat = (
|
|
43
|
+
let buttonWidth = (UIScreen.main.bounds.width - SEPARATOR_WIDTH * 2 - 4 * SEPARATOR_WIDTH) / 5
|
|
44
|
+
let buttonHeight: CGFloat = (240 - SEPARATOR_WIDTH * 2 - 3 * SEPARATOR_WIDTH) / 4
|
|
39
45
|
|
|
40
46
|
// Create a wrapper view
|
|
41
47
|
let contentView = UIView()
|
|
@@ -52,19 +58,22 @@ class CalculatorKeyboardView: UIView {
|
|
|
52
58
|
|
|
53
59
|
// Add buttons to the wrapper view
|
|
54
60
|
var yOffset: CGFloat = 0
|
|
55
|
-
for row in keys {
|
|
61
|
+
for (rowIndex, row) in keys.enumerated() {
|
|
56
62
|
var xOffset: CGFloat = 0
|
|
57
|
-
for key in row {
|
|
63
|
+
for (colIndex, key) in row.enumerated() {
|
|
64
|
+
let isCustomKey = colIndex == 4 && rowIndex == 2
|
|
58
65
|
let button = UIButton(type: .system)
|
|
59
66
|
button.backgroundColor = UIColor.white
|
|
60
67
|
button.layer.cornerRadius = 8
|
|
61
|
-
|
|
68
|
+
let title = isCustomKey ? (customKeyText ?? key) : key
|
|
69
|
+
button.setTitle(title, for: .normal)
|
|
62
70
|
button.setTitleColor(.black, for: .normal)
|
|
63
|
-
button.titleLabel?.font = UIFont.systemFont(ofSize: 24, weight: .medium)
|
|
71
|
+
button.titleLabel?.font = UIFont.systemFont(ofSize: isCustomKey ? 18 : 24, weight: .medium)
|
|
64
72
|
button.nativeID = key
|
|
73
|
+
button.tag = isCustomKey ? 1 : 0
|
|
65
74
|
|
|
66
75
|
var buttonFrame = CGRect(x: xOffset, y: yOffset, width: buttonWidth, height: buttonHeight)
|
|
67
|
-
if
|
|
76
|
+
if isCustomKey {
|
|
68
77
|
buttonFrame.size.height = buttonHeight * 2 + SEPARATOR_WIDTH
|
|
69
78
|
}
|
|
70
79
|
if key == "000" {
|
|
@@ -85,6 +94,10 @@ class CalculatorKeyboardView: UIView {
|
|
|
85
94
|
button.backgroundColor = color
|
|
86
95
|
}
|
|
87
96
|
|
|
97
|
+
if isCustomKey {
|
|
98
|
+
self.customKeyButton = button
|
|
99
|
+
}
|
|
100
|
+
|
|
88
101
|
button.addTarget(self, action: #selector(keyPressed(_:)), for: .touchUpInside)
|
|
89
102
|
contentView.addSubview(button)
|
|
90
103
|
|
|
@@ -96,12 +109,37 @@ class CalculatorKeyboardView: UIView {
|
|
|
96
109
|
}
|
|
97
110
|
}
|
|
98
111
|
|
|
112
|
+
private func updateCustomKeyTitle() {
|
|
113
|
+
guard let btn = customKeyButton, let title = customKeyText else { return }
|
|
114
|
+
btn.setTitle(title, for: .normal)
|
|
115
|
+
btn.setImage(nil, for: .normal)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private func updateCustomKeyBackground() {
|
|
119
|
+
guard let btn = customKeyButton,
|
|
120
|
+
let background = customKeyBackground,
|
|
121
|
+
let textColor = customKeyTextColor,
|
|
122
|
+
let state = customKeyState else { return }
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
btn.isEnabled = state != "disable"
|
|
127
|
+
btn.backgroundColor = UIColor(hex: background)
|
|
128
|
+
btn.setTitleColor(UIColor(hex: textColor), for: .normal)
|
|
129
|
+
|
|
130
|
+
}
|
|
131
|
+
|
|
99
132
|
|
|
100
133
|
@objc private func keyPressed(_ sender: UIButton) {
|
|
101
134
|
guard let key = sender.nativeID else { return }
|
|
135
|
+
let isCustomKey = sender.tag == 1
|
|
136
|
+
if (isCustomKey) {
|
|
137
|
+
input?.emitCustomKey()
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
input?.emitKeyPress(key)
|
|
102
142
|
switch key {
|
|
103
|
-
case "AC":
|
|
104
|
-
input?.clearText()
|
|
105
143
|
case "back":
|
|
106
144
|
input?.onBackSpace()
|
|
107
145
|
case "=":
|
package/ios/InputCalculator.m
CHANGED
|
@@ -56,6 +56,8 @@ RCT_EXPORT_SHADOW_PROPERTY(onContentSizeChange, RCTDirectEventBlock)
|
|
|
56
56
|
RCT_EXPORT_VIEW_PROPERTY(value, NSString)
|
|
57
57
|
RCT_EXPORT_VIEW_PROPERTY(onFocus, RCTBubblingEventBlock)
|
|
58
58
|
RCT_EXPORT_VIEW_PROPERTY(onBlur, RCTBubblingEventBlock)
|
|
59
|
+
RCT_EXPORT_VIEW_PROPERTY(onKeyPress, RCTBubblingEventBlock)
|
|
60
|
+
RCT_EXPORT_VIEW_PROPERTY(onCustomKeyEvent, RCTDirectEventBlock)
|
|
59
61
|
|
|
60
62
|
RCT_EXPORT_METHOD(focus : (nonnull NSNumber *)viewTag)
|
|
61
63
|
{
|
|
@@ -74,6 +76,10 @@ RCT_EXPORT_METHOD(blur : (nonnull NSNumber *)viewTag)
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
RCT_EXPORT_VIEW_PROPERTY(keyboardColor, UIColor)
|
|
79
|
+
RCT_EXPORT_VIEW_PROPERTY(customKeyText, NSString)
|
|
80
|
+
RCT_EXPORT_VIEW_PROPERTY(customKeyBackground, NSString)
|
|
81
|
+
RCT_EXPORT_VIEW_PROPERTY(customKeyTextColor, NSString)
|
|
82
|
+
RCT_EXPORT_VIEW_PROPERTY(customKeyState, NSString)
|
|
77
83
|
|
|
78
84
|
@end
|
|
79
85
|
|
|
@@ -19,6 +19,24 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
19
19
|
|
|
20
20
|
@objc var onFocus: RCTBubblingEventBlock?
|
|
21
21
|
@objc var onBlur: RCTBubblingEventBlock?
|
|
22
|
+
@objc var onKeyPress: RCTBubblingEventBlock?
|
|
23
|
+
@objc var onCustomKeyEvent: RCTDirectEventBlock?
|
|
24
|
+
|
|
25
|
+
@objc var customKeyText: String? {
|
|
26
|
+
didSet { keyboardView?.customKeyText = customKeyText as String? }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@objc var customKeyBackground: String? {
|
|
30
|
+
didSet { keyboardView?.customKeyBackground = customKeyBackground }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@objc var customKeyTextColor: String? {
|
|
34
|
+
didSet { keyboardView?.customKeyTextColor = customKeyTextColor }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@objc var customKeyState: String? {
|
|
38
|
+
didSet { keyboardView?.customKeyState = customKeyState }
|
|
39
|
+
}
|
|
22
40
|
|
|
23
41
|
@objc func beginEditingInput(_ note: Notification) { onFocus?([:]) }
|
|
24
42
|
@objc func endEditingInput(_ note: Notification) { onBlur?([:]) }
|
|
@@ -50,7 +68,7 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
50
68
|
super.init(bridge: bridge)
|
|
51
69
|
self.bridge = bridge
|
|
52
70
|
self.keyboardView = CalculatorKeyboardView()
|
|
53
|
-
self.keyboardView!.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height:
|
|
71
|
+
self.keyboardView!.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 240 + getbottomInset())
|
|
54
72
|
self.keyboardView!.input = self
|
|
55
73
|
|
|
56
74
|
backedTextInputView.inputView = self.keyboardView
|
|
@@ -79,19 +97,12 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
79
97
|
func keyDidPress(_ key: String) {
|
|
80
98
|
backedTextInputView.insertText(key)
|
|
81
99
|
value += key
|
|
100
|
+
|
|
82
101
|
if let bridge = bridge {
|
|
83
102
|
bridge.eventDispatcher().sendTextEvent(with: .change, reactTag: reactTag, text: value, key: "\(key)", eventCount: 1)
|
|
84
103
|
}
|
|
85
104
|
}
|
|
86
105
|
|
|
87
|
-
func clearText() {
|
|
88
|
-
value = ""
|
|
89
|
-
(backedTextInputView as? UITextField)?.text = ""
|
|
90
|
-
if let bridge = bridge {
|
|
91
|
-
bridge.eventDispatcher().sendTextEvent(with: .change, reactTag: reactTag, text: value, key: "clear", eventCount: 1)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
106
|
func onBackSpace() {
|
|
96
107
|
value = value.dropLast().description
|
|
97
108
|
DispatchQueue.main.async {
|
|
@@ -102,7 +113,7 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
102
113
|
self.backedTextInputView.replace(newRange, withText: "")
|
|
103
114
|
}
|
|
104
115
|
}
|
|
105
|
-
|
|
116
|
+
|
|
106
117
|
if let bridge = bridge {
|
|
107
118
|
bridge.eventDispatcher().sendTextEvent(with: .change, reactTag: reactTag, text: value, key: "back", eventCount: 1)
|
|
108
119
|
}
|
|
@@ -124,6 +135,7 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
124
135
|
if let result = expression.expressionValue(with: nil, context: nil) as? NSNumber {
|
|
125
136
|
textField.text = result.stringValue
|
|
126
137
|
value = result.stringValue
|
|
138
|
+
|
|
127
139
|
if let bridge = bridge {
|
|
128
140
|
bridge.eventDispatcher().sendTextEvent(with: .change, reactTag: reactTag, text: value, key: "=", eventCount: 1)
|
|
129
141
|
}
|
|
@@ -133,6 +145,14 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
133
145
|
print("Invalid expression")
|
|
134
146
|
}
|
|
135
147
|
}
|
|
148
|
+
|
|
149
|
+
func emitCustomKey() {
|
|
150
|
+
onCustomKeyEvent?([:])
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
func emitKeyPress(_ key: String) {
|
|
154
|
+
onKeyPress?(["key": key])
|
|
155
|
+
}
|
|
136
156
|
|
|
137
157
|
}
|
|
138
158
|
|
package/package.json
CHANGED
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/calculator-keyboard",
|
|
3
|
-
"version": "0.150.2-beta.
|
|
3
|
+
"version": "0.150.2-beta.20",
|
|
4
4
|
"description": "react native calculator keyboard",
|
|
5
|
-
"
|
|
6
|
-
"main": "./lib/commonjs/index.js",
|
|
7
|
-
"module": "./lib/module/index.js",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"import": {
|
|
11
|
-
"types": "./lib/typescript/module/src/index.d.ts",
|
|
12
|
-
"default": "./lib/module/index.js"
|
|
13
|
-
},
|
|
14
|
-
"require": {
|
|
15
|
-
"types": "./lib/typescript/commonjs/src/index.d.ts",
|
|
16
|
-
"default": "./lib/commonjs/index.js"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
},
|
|
5
|
+
"main": "./src/index.tsx",
|
|
20
6
|
"files": [
|
|
21
7
|
"src",
|
|
22
8
|
"lib",
|
|
@@ -41,7 +27,7 @@
|
|
|
41
27
|
"typecheck": "tsc",
|
|
42
28
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
43
29
|
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
44
|
-
"build": "
|
|
30
|
+
"build": "echo 'build step'",
|
|
45
31
|
"release": "release-it"
|
|
46
32
|
},
|
|
47
33
|
"keywords": [
|
|
@@ -63,123 +49,13 @@
|
|
|
63
49
|
"registry": "https://registry.npmjs.org/"
|
|
64
50
|
},
|
|
65
51
|
"devDependencies": {
|
|
66
|
-
"@commitlint/config-conventional": "^17.0.2",
|
|
67
|
-
"@evilmartians/lefthook": "^1.5.0",
|
|
68
|
-
"@react-native-community/cli": "15.0.1",
|
|
69
|
-
"@react-native/eslint-config": "^0.73.1",
|
|
70
|
-
"@release-it/conventional-changelog": "^9.0.2",
|
|
71
|
-
"@types/jest": "^29.5.5",
|
|
72
|
-
"@types/react": "^18.2.44",
|
|
73
|
-
"commitlint": "^17.0.2",
|
|
74
|
-
"del-cli": "^5.1.0",
|
|
75
|
-
"eslint": "^8.51.0",
|
|
76
|
-
"eslint-config-prettier": "^9.0.0",
|
|
77
|
-
"eslint-plugin-prettier": "^5.0.1",
|
|
78
|
-
"jest": "^29.7.0",
|
|
79
|
-
"prettier": "^3.0.3",
|
|
80
|
-
"react": "18.3.1",
|
|
81
|
-
"react-native": "0.76.5",
|
|
82
|
-
"react-native-builder-bob": "^0.32.0",
|
|
83
|
-
"release-it": "^17.10.0",
|
|
84
|
-
"turbo": "^1.10.7",
|
|
85
|
-
"typescript": "^5.2.2"
|
|
86
|
-
},
|
|
87
|
-
"resolutions": {
|
|
88
|
-
"@types/react": "^18.2.44"
|
|
89
|
-
},
|
|
90
|
-
"peerDependencies": {
|
|
91
52
|
"react": "*",
|
|
92
53
|
"react-native": "*"
|
|
93
54
|
},
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
|
|
98
|
-
"<rootDir>/lib/"
|
|
99
|
-
]
|
|
100
|
-
},
|
|
101
|
-
"commitlint": {
|
|
102
|
-
"extends": [
|
|
103
|
-
"@commitlint/config-conventional"
|
|
104
|
-
]
|
|
105
|
-
},
|
|
106
|
-
"release-it": {
|
|
107
|
-
"git": {
|
|
108
|
-
"commitMessage": "chore: release ${version}",
|
|
109
|
-
"tagName": "v${version}"
|
|
110
|
-
},
|
|
111
|
-
"npm": {
|
|
112
|
-
"publish": true
|
|
113
|
-
},
|
|
114
|
-
"github": {
|
|
115
|
-
"release": true
|
|
116
|
-
},
|
|
117
|
-
"plugins": {
|
|
118
|
-
"@release-it/conventional-changelog": {
|
|
119
|
-
"preset": "angular"
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
"eslintConfig": {
|
|
124
|
-
"root": true,
|
|
125
|
-
"extends": [
|
|
126
|
-
"@react-native",
|
|
127
|
-
"prettier"
|
|
128
|
-
],
|
|
129
|
-
"rules": {
|
|
130
|
-
"react/react-in-jsx-scope": "off",
|
|
131
|
-
"prettier/prettier": [
|
|
132
|
-
"error",
|
|
133
|
-
{
|
|
134
|
-
"quoteProps": "consistent",
|
|
135
|
-
"singleQuote": true,
|
|
136
|
-
"tabWidth": 2,
|
|
137
|
-
"trailingComma": "es5",
|
|
138
|
-
"useTabs": false
|
|
139
|
-
}
|
|
140
|
-
]
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
"eslintIgnore": [
|
|
144
|
-
"node_modules/",
|
|
145
|
-
"lib/"
|
|
146
|
-
],
|
|
147
|
-
"prettier": {
|
|
148
|
-
"quoteProps": "consistent",
|
|
149
|
-
"singleQuote": true,
|
|
150
|
-
"tabWidth": 2,
|
|
151
|
-
"trailingComma": "es5",
|
|
152
|
-
"useTabs": false
|
|
153
|
-
},
|
|
154
|
-
"react-native-builder-bob": {
|
|
155
|
-
"source": "src",
|
|
156
|
-
"output": "lib",
|
|
157
|
-
"targets": [
|
|
158
|
-
[
|
|
159
|
-
"commonjs",
|
|
160
|
-
{
|
|
161
|
-
"esm": true
|
|
162
|
-
}
|
|
163
|
-
],
|
|
164
|
-
[
|
|
165
|
-
"module",
|
|
166
|
-
{
|
|
167
|
-
"esm": true
|
|
168
|
-
}
|
|
169
|
-
],
|
|
170
|
-
[
|
|
171
|
-
"typescript",
|
|
172
|
-
{
|
|
173
|
-
"project": "tsconfig.build.json",
|
|
174
|
-
"esm": true
|
|
175
|
-
}
|
|
176
|
-
]
|
|
177
|
-
]
|
|
178
|
-
},
|
|
179
|
-
"create-react-native-library": {
|
|
180
|
-
"type": "legacy-view",
|
|
181
|
-
"languages": "kotlin-swift",
|
|
182
|
-
"version": "0.45.5"
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"react": "*",
|
|
57
|
+
"react-native": "*",
|
|
58
|
+
"@momo-kits/foundation": "latest"
|
|
183
59
|
},
|
|
184
60
|
"dependencies": {}
|
|
185
61
|
}
|