react-native-controlled-input 0.10.0 → 0.12.0
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 +9 -3
- package/android/src/main/java/com/controlledinput/ControlledInputView.kt +3 -0
- package/android/src/main/java/com/controlledinput/ControlledInputViewManager.kt +15 -0
- package/android/src/main/java/com/controlledinput/JetpackComposeView.kt +75 -43
- package/android/src/main/java/com/controlledinput/JetpackComposeViewModel.kt +18 -0
- package/ios/ControlledInputView.mm +12 -0
- package/ios/RNControlledInput.swift +32 -0
- package/lib/module/ControlledInputViewNativeComponent.ts +3 -0
- package/lib/module/index.js +46 -10
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/ControlledInputViewNativeComponent.d.ts +3 -0
- package/lib/typescript/src/ControlledInputViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ControlledInputViewNativeComponent.ts +3 -0
- package/src/index.tsx +75 -11
- package/src/react-native-codegen.d.ts +16 -0
package/README.md
CHANGED
|
@@ -68,9 +68,15 @@ inputRef.current?.blur();
|
|
|
68
68
|
|------|------|-------------|
|
|
69
69
|
| `value` | `string` | Current input value. |
|
|
70
70
|
| `onTextChange` | `(value: string) => void` | Called with the next text value. Filter it and update `value`. |
|
|
71
|
-
| `onFocus` | `() => void` | Called
|
|
72
|
-
| `onBlur` | `() => void` | Called
|
|
73
|
-
| `
|
|
71
|
+
| `onFocus` | `() => void` | Called when the text input is focused. |
|
|
72
|
+
| `onBlur` | `() => void` | Called when the text input is blurred. |
|
|
73
|
+
| `autoComplete` | `string` | Specifies autocomplete hints for the system. Same as React Native [`TextInput`](https://reactnative.dev/docs/textinput#autocomplete). |
|
|
74
|
+
| `autoCapitalize` | `string` | Can be `none`, `sentences`, `words`, `characters`. Same as React Native [`TextInput`](https://reactnative.dev/docs/textinput#autocapitalize). |
|
|
75
|
+
| `keyboardType` | `string` | Determines which keyboard to open, e.g. `numeric`. Same as React Native [`TextInput`](https://reactnative.dev/docs/textinput#keyboardtype). |
|
|
76
|
+
| `returnKeyType` | `string` | Determines how the return key should look. Same as React Native [`TextInput`](https://reactnative.dev/docs/textinput#returnkeytype). |
|
|
77
|
+
| `placeholder` | `string` | The string that will be rendered before text input has been entered. |
|
|
78
|
+
| `placeholderTextColor` | `ColorValue` | The text color of the placeholder string. |
|
|
79
|
+
| `selectionColor` | `ColorValue` | The highlight and cursor color of the text input. |
|
|
74
80
|
|
|
75
81
|
## Style support
|
|
76
82
|
|
|
@@ -95,6 +95,9 @@ class ControlledInputView : LinearLayout {
|
|
|
95
95
|
value = value,
|
|
96
96
|
inputStyle = viewModel.inputStyle,
|
|
97
97
|
autoComplete = viewModel.autoComplete,
|
|
98
|
+
placeholder = viewModel.placeholder,
|
|
99
|
+
placeholderTextColor = viewModel.placeholderTextColor,
|
|
100
|
+
selectionColor = viewModel.selectionColor,
|
|
98
101
|
autoCapitalize = viewModel.autoCapitalize,
|
|
99
102
|
keyboardType = viewModel.keyboardType,
|
|
100
103
|
returnKeyType = viewModel.returnKeyType,
|
|
@@ -38,6 +38,21 @@ class ControlledInputViewManager : SimpleViewManager<ControlledInputView>(),
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
@ReactProp(name = "placeholder")
|
|
42
|
+
override fun setPlaceholder(view: ControlledInputView, placeholder: String?) {
|
|
43
|
+
view.viewModel.setPlaceholder(placeholder)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@ReactProp(name = "placeholderTextColor", customType = "Color")
|
|
47
|
+
override fun setPlaceholderTextColor(view: ControlledInputView, placeholderTextColor: Int?) {
|
|
48
|
+
view.viewModel.setPlaceholderTextColor(placeholderTextColor)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@ReactProp(name = "selectionColor", customType = "Color")
|
|
52
|
+
override fun setSelectionColor(view: ControlledInputView, selectionColor: Int?) {
|
|
53
|
+
view.viewModel.setSelectionColor(selectionColor)
|
|
54
|
+
}
|
|
55
|
+
|
|
41
56
|
@ReactProp(name = "autoComplete")
|
|
42
57
|
override fun setAutoComplete(view: ControlledInputView, autoComplete: String?) {
|
|
43
58
|
view.viewModel.setAutoCompleteWithAutofill(view, autoComplete)
|
|
@@ -26,6 +26,9 @@ import androidx.compose.ui.Modifier
|
|
|
26
26
|
import androidx.compose.ui.focus.FocusRequester
|
|
27
27
|
import androidx.compose.ui.focus.focusRequester
|
|
28
28
|
import android.graphics.Typeface
|
|
29
|
+
import androidx.compose.foundation.text.selection.LocalTextSelectionColors
|
|
30
|
+
import androidx.compose.foundation.text.selection.TextSelectionColors
|
|
31
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
29
32
|
import androidx.compose.ui.graphics.Color
|
|
30
33
|
import androidx.compose.ui.platform.LocalContext
|
|
31
34
|
import androidx.compose.ui.text.TextStyle
|
|
@@ -64,6 +67,9 @@ fun JetpackComposeView(
|
|
|
64
67
|
value: String,
|
|
65
68
|
inputStyle: StateFlow<InputStyle?>,
|
|
66
69
|
autoComplete: StateFlow<String?>,
|
|
70
|
+
placeholder: StateFlow<String?>,
|
|
71
|
+
placeholderTextColor: StateFlow<Int?>,
|
|
72
|
+
selectionColor: StateFlow<Int?>,
|
|
67
73
|
autoCapitalize: StateFlow<String?>,
|
|
68
74
|
keyboardType: StateFlow<String?>,
|
|
69
75
|
returnKeyType: StateFlow<String?>,
|
|
@@ -78,6 +84,9 @@ fun JetpackComposeView(
|
|
|
78
84
|
val autoCapitalizeValue by autoCapitalize.collectAsState()
|
|
79
85
|
val returnKeyTypeValue by returnKeyType.collectAsState()
|
|
80
86
|
val autoCompleteValue by autoComplete.collectAsState()
|
|
87
|
+
val placeholderValue by placeholder.collectAsState()
|
|
88
|
+
val placeholderTextColorValue by placeholderTextColor.collectAsState()
|
|
89
|
+
val selectionColorValue by selectionColor.collectAsState()
|
|
81
90
|
val interactionSource = remember { MutableInteractionSource() }
|
|
82
91
|
|
|
83
92
|
val autofill = LocalAutofill.current
|
|
@@ -137,51 +146,74 @@ fun JetpackComposeView(
|
|
|
137
146
|
?: Color.Transparent
|
|
138
147
|
val shape = RoundedCornerShape(borderRadius)
|
|
139
148
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
onTextChange(proposed.toString())
|
|
151
|
-
proposed
|
|
152
|
-
},
|
|
149
|
+
val cursorColor = selectionColorValue?.let { Color(it) } ?: textColor
|
|
150
|
+
val textSelectionColors = remember(cursorColor) {
|
|
151
|
+
TextSelectionColors(
|
|
152
|
+
handleColor = cursorColor,
|
|
153
|
+
backgroundColor = cursorColor.copy(alpha = 0.4f)
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
CompositionLocalProvider(LocalTextSelectionColors provides textSelectionColors) {
|
|
158
|
+
Box(
|
|
153
159
|
modifier = Modifier
|
|
154
160
|
.fillMaxSize()
|
|
155
|
-
.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
161
|
+
.clip(shape)
|
|
162
|
+
.background(backgroundColor)
|
|
163
|
+
.border(borderWidth, borderColor, shape),
|
|
164
|
+
) {
|
|
165
|
+
BasicTextField(
|
|
166
|
+
state,
|
|
167
|
+
inputTransformation = InputTransformation.byValue { _, proposed ->
|
|
168
|
+
onTextChange(proposed.toString())
|
|
169
|
+
proposed
|
|
170
|
+
},
|
|
171
|
+
modifier = Modifier
|
|
172
|
+
.fillMaxSize()
|
|
173
|
+
.padding(
|
|
174
|
+
start = paddingLeft,
|
|
175
|
+
top = paddingTop,
|
|
176
|
+
end = paddingRight,
|
|
177
|
+
bottom = paddingBottom,
|
|
178
|
+
)
|
|
179
|
+
.onGloballyPositioned {
|
|
180
|
+
autofillNode.boundingBox = it.boundsInWindow()
|
|
181
|
+
}
|
|
182
|
+
.focusRequester(focusRequester),
|
|
183
|
+
textStyle = TextStyle(
|
|
184
|
+
color = textColor,
|
|
185
|
+
fontSize = fontSize,
|
|
186
|
+
fontFamily = fontFamily,
|
|
187
|
+
),
|
|
188
|
+
keyboardOptions = KeyboardOptions(
|
|
189
|
+
capitalization = toComposeCapitalization(autoCapitalizeValue),
|
|
190
|
+
keyboardType = toComposeKeyboardType(keyboardTypeValue),
|
|
191
|
+
imeAction = toComposeImeAction(returnKeyTypeValue),
|
|
192
|
+
),
|
|
193
|
+
interactionSource = interactionSource,
|
|
194
|
+
cursorBrush = androidx.compose.ui.graphics.SolidColor(cursorColor),
|
|
195
|
+
decorator = { innerTextField ->
|
|
196
|
+
Box(
|
|
197
|
+
modifier = Modifier.fillMaxSize(),
|
|
198
|
+
contentAlignment = Alignment.CenterStart,
|
|
199
|
+
) {
|
|
200
|
+
if (state.text.isEmpty() && !placeholderValue.isNullOrEmpty()) {
|
|
201
|
+
val finalPlaceholderColor = placeholderTextColorValue?.let { Color(it) }
|
|
202
|
+
?: textColor.copy(alpha = 0.5f)
|
|
203
|
+
androidx.compose.material3.Text(
|
|
204
|
+
text = placeholderValue!!,
|
|
205
|
+
style = TextStyle(
|
|
206
|
+
color = finalPlaceholderColor,
|
|
207
|
+
fontSize = fontSize,
|
|
208
|
+
fontFamily = fontFamily,
|
|
209
|
+
)
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
innerTextField()
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
)
|
|
216
|
+
}
|
|
185
217
|
}
|
|
186
218
|
}
|
|
187
219
|
|
|
@@ -10,6 +10,9 @@ class JetpackComposeViewModel : ViewModel() {
|
|
|
10
10
|
private val _value = MutableStateFlow("")
|
|
11
11
|
private val _inputStyle = MutableStateFlow<InputStyle?>(null)
|
|
12
12
|
private val _autoComplete = MutableStateFlow<String?>(null)
|
|
13
|
+
private val _placeholder = MutableStateFlow<String?>(null)
|
|
14
|
+
private val _placeholderTextColor = MutableStateFlow<Int?>(null)
|
|
15
|
+
private val _selectionColor = MutableStateFlow<Int?>(null)
|
|
13
16
|
private val _autoCapitalize = MutableStateFlow<String?>(null)
|
|
14
17
|
private val _keyboardType = MutableStateFlow<String?>(null)
|
|
15
18
|
private val _returnKeyType = MutableStateFlow<String?>(null)
|
|
@@ -17,6 +20,9 @@ class JetpackComposeViewModel : ViewModel() {
|
|
|
17
20
|
val value: StateFlow<String> get() = _value
|
|
18
21
|
val inputStyle: StateFlow<InputStyle?> get() = _inputStyle
|
|
19
22
|
val autoComplete: StateFlow<String?> get() = _autoComplete
|
|
23
|
+
val placeholder: StateFlow<String?> get() = _placeholder
|
|
24
|
+
val placeholderTextColor: StateFlow<Int?> get() = _placeholderTextColor
|
|
25
|
+
val selectionColor: StateFlow<Int?> get() = _selectionColor
|
|
20
26
|
val autoCapitalize: StateFlow<String?> get() = _autoCapitalize
|
|
21
27
|
val keyboardType: StateFlow<String?> get() = _keyboardType
|
|
22
28
|
val returnKeyType: StateFlow<String?> get() = _returnKeyType
|
|
@@ -33,6 +39,18 @@ class JetpackComposeViewModel : ViewModel() {
|
|
|
33
39
|
_autoComplete.value = newValue
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
fun setPlaceholder(newValue: String?) {
|
|
43
|
+
_placeholder.value = newValue
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fun setPlaceholderTextColor(newValue: Int?) {
|
|
47
|
+
_placeholderTextColor.value = newValue
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fun setSelectionColor(newValue: Int?) {
|
|
51
|
+
_selectionColor.value = newValue
|
|
52
|
+
}
|
|
53
|
+
|
|
36
54
|
fun setAutoCompleteWithAutofill(hostView: View, newValue: String?) {
|
|
37
55
|
setAutoComplete(newValue)
|
|
38
56
|
|
|
@@ -68,6 +68,18 @@ using namespace facebook::react;
|
|
|
68
68
|
_inputView.autoCapitalize = newViewProps.autoCapitalize.empty() ? nil : [NSString stringWithUTF8String:newViewProps.autoCapitalize.c_str()];
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
if (oldViewProps.placeholder != newViewProps.placeholder) {
|
|
72
|
+
_inputView.placeholder = newViewProps.placeholder.empty() ? nil : [NSString stringWithUTF8String:newViewProps.placeholder.c_str()];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (oldViewProps.placeholderTextColor != newViewProps.placeholderTextColor) {
|
|
76
|
+
_inputView.placeholderTextColor = RCTUIColorFromSharedColor(newViewProps.placeholderTextColor);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (oldViewProps.selectionColor != newViewProps.selectionColor) {
|
|
80
|
+
_inputView.selectionColor = RCTUIColorFromSharedColor(newViewProps.selectionColor);
|
|
81
|
+
}
|
|
82
|
+
|
|
71
83
|
const auto &style = newViewProps.inputStyle;
|
|
72
84
|
const auto &oldStyle = oldViewProps.inputStyle;
|
|
73
85
|
|
|
@@ -48,6 +48,18 @@ public class RNControlledInput: UIView, UITextFieldDelegate {
|
|
|
48
48
|
didSet { applyReturnKeyType() }
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
@objc public var placeholder: String? {
|
|
52
|
+
didSet { applyPlaceholder() }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@objc public var placeholderTextColor: UIColor? {
|
|
56
|
+
didSet { applyPlaceholder() }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc public var selectionColor: UIColor? {
|
|
60
|
+
didSet { textField.tintColor = selectionColor }
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
public override var canBecomeFirstResponder: Bool { true }
|
|
52
64
|
|
|
53
65
|
@objc public func focus() {
|
|
@@ -71,6 +83,7 @@ public class RNControlledInput: UIView, UITextFieldDelegate {
|
|
|
71
83
|
textField.translatesAutoresizingMaskIntoConstraints = false
|
|
72
84
|
textField.borderStyle = .none
|
|
73
85
|
textField.delegate = self
|
|
86
|
+
textField.textColor = textColor
|
|
74
87
|
addSubview(textField)
|
|
75
88
|
|
|
76
89
|
NSLayoutConstraint.activate([
|
|
@@ -85,6 +98,25 @@ public class RNControlledInput: UIView, UITextFieldDelegate {
|
|
|
85
98
|
applyAutoCapitalize()
|
|
86
99
|
applyKeyboardType()
|
|
87
100
|
applyReturnKeyType()
|
|
101
|
+
applyPlaceholder()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private func applyPlaceholder() {
|
|
105
|
+
guard let placeholder = placeholder else {
|
|
106
|
+
textField.attributedPlaceholder = nil
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
var attributes: [NSAttributedString.Key: Any] = [:]
|
|
111
|
+
if let placeholderTextColor = placeholderTextColor {
|
|
112
|
+
attributes[.foregroundColor] = placeholderTextColor
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
textField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: attributes)
|
|
116
|
+
|
|
117
|
+
if let color = textColor {
|
|
118
|
+
textField.textColor = color
|
|
119
|
+
}
|
|
88
120
|
}
|
|
89
121
|
|
|
90
122
|
public func textFieldDidBeginEditing(_ textField: UITextField) {
|
|
@@ -38,6 +38,9 @@ export interface InputStyle {
|
|
|
38
38
|
|
|
39
39
|
export interface NativeProps extends ViewProps {
|
|
40
40
|
value?: string;
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
placeholderTextColor?: ColorValue;
|
|
43
|
+
selectionColor?: ColorValue;
|
|
41
44
|
autoComplete?: string;
|
|
42
45
|
autoCapitalize?: string;
|
|
43
46
|
keyboardType?: string;
|
package/lib/module/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { forwardRef, memo, useImperativeHandle, useRef } from 'react';
|
|
3
|
+
import { forwardRef, memo, useImperativeHandle, useLayoutEffect, useRef } from 'react';
|
|
4
4
|
import { Platform, processColor, StyleSheet } from 'react-native';
|
|
5
|
-
|
|
5
|
+
// TextInputState is not exported from the public react-native package.
|
|
6
|
+
// eslint-disable-next-line @react-native/no-deep-imports -- integrate with ScrollView keyboard dismissal
|
|
7
|
+
import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
|
|
8
|
+
import ControlledInputViewNativeComponent from './ControlledInputViewNativeComponent';
|
|
6
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
10
|
// All style props that Android handles via Compose instead of the native View layer
|
|
8
11
|
const androidComposeHandledKeys = ['color', 'fontSize', 'fontFamily', 'padding', 'paddingVertical', 'paddingHorizontal', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', 'borderWidth', 'borderRadius', 'borderColor', 'backgroundColor'];
|
|
@@ -18,9 +21,30 @@ function resolveAndroidComposeViewPadding(flat) {
|
|
|
18
21
|
export const ControlledInputView = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(({
|
|
19
22
|
style,
|
|
20
23
|
onTextChange,
|
|
24
|
+
onFocus,
|
|
25
|
+
onBlur,
|
|
26
|
+
selectionColor,
|
|
27
|
+
placeholderTextColor,
|
|
21
28
|
...rest
|
|
22
29
|
}, ref) => {
|
|
23
30
|
const nativeRef = useRef(null);
|
|
31
|
+
const isNativePlatform = Platform.OS === 'ios' || Platform.OS === 'android';
|
|
32
|
+
useLayoutEffect(() => {
|
|
33
|
+
if (!isNativePlatform) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const node = nativeRef.current;
|
|
37
|
+
if (node == null) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
TextInputState.registerInput(node);
|
|
41
|
+
return () => {
|
|
42
|
+
TextInputState.unregisterInput(node);
|
|
43
|
+
if (TextInputState.currentlyFocusedInput() === node) {
|
|
44
|
+
TextInputState.blurTextInput(node);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}, [isNativePlatform]);
|
|
24
48
|
const flattenedStyle = StyleSheet.flatten(style) ?? {};
|
|
25
49
|
let viewStyle;
|
|
26
50
|
let inputStyle;
|
|
@@ -57,25 +81,37 @@ export const ControlledInputView = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(({
|
|
|
57
81
|
onTextChange(e.nativeEvent.value);
|
|
58
82
|
}
|
|
59
83
|
};
|
|
84
|
+
const handleFocus = e => {
|
|
85
|
+
if (isNativePlatform) {
|
|
86
|
+
TextInputState.focusInput(nativeRef.current);
|
|
87
|
+
}
|
|
88
|
+
onFocus?.(e);
|
|
89
|
+
};
|
|
90
|
+
const handleBlur = e => {
|
|
91
|
+
if (isNativePlatform) {
|
|
92
|
+
TextInputState.blurInput(nativeRef.current);
|
|
93
|
+
}
|
|
94
|
+
onBlur?.(e);
|
|
95
|
+
};
|
|
60
96
|
useImperativeHandle(ref, () => ({
|
|
61
97
|
blur: () => {
|
|
62
|
-
if (!nativeRef.current) return;
|
|
63
|
-
|
|
64
|
-
Commands.blur(nativeRef.current);
|
|
65
|
-
}
|
|
98
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
99
|
+
TextInputState.blurTextInput(nativeRef.current);
|
|
66
100
|
},
|
|
67
101
|
focus: () => {
|
|
68
|
-
if (!nativeRef.current) return;
|
|
69
|
-
|
|
70
|
-
Commands.focus(nativeRef.current);
|
|
71
|
-
}
|
|
102
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
103
|
+
TextInputState.focusTextInput(nativeRef.current);
|
|
72
104
|
}
|
|
73
105
|
}));
|
|
74
106
|
return /*#__PURE__*/_jsx(ControlledInputViewNativeComponent, {
|
|
75
107
|
...rest,
|
|
108
|
+
placeholderTextColor: placeholderTextColor,
|
|
109
|
+
selectionColor: selectionColor,
|
|
76
110
|
style: viewStyle,
|
|
77
111
|
inputStyle: inputStyle,
|
|
78
112
|
onTextChange: handleTextChange,
|
|
113
|
+
onFocus: handleFocus,
|
|
114
|
+
onBlur: handleBlur,
|
|
79
115
|
ref: nativeRef
|
|
80
116
|
});
|
|
81
117
|
}));
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["forwardRef","memo","useImperativeHandle","useRef","Platform","processColor","StyleSheet","
|
|
1
|
+
{"version":3,"names":["forwardRef","memo","useImperativeHandle","useLayoutEffect","useRef","Platform","processColor","StyleSheet","TextInputState","ControlledInputViewNativeComponent","jsx","_jsx","androidComposeHandledKeys","resolveAndroidComposeViewPadding","flat","padding","paddingTop","paddingVertical","paddingBottom","paddingLeft","paddingHorizontal","paddingRight","ControlledInputView","style","onTextChange","onFocus","onBlur","selectionColor","placeholderTextColor","rest","ref","nativeRef","isNativePlatform","OS","node","current","registerInput","unregisterInput","currentlyFocusedInput","blurTextInput","flattenedStyle","flatten","viewStyle","inputStyle","Object","fromEntries","entries","filter","k","includes","hasPadding","some","v","color","fontSize","fontFamily","borderWidth","borderRadius","borderColor","backgroundColor","iosViewStyle","hasTextStyle","undefined","handleTextChange","e","nativeEvent","value","handleFocus","focusInput","handleBlur","blurInput","blur","focus","focusTextInput","displayName"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -22,6 +22,9 @@ export interface InputStyle {
|
|
|
22
22
|
}
|
|
23
23
|
export interface NativeProps extends ViewProps {
|
|
24
24
|
value?: string;
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
placeholderTextColor?: ColorValue;
|
|
27
|
+
selectionColor?: ColorValue;
|
|
25
28
|
autoComplete?: string;
|
|
26
29
|
autoCapitalize?: string;
|
|
27
30
|
keyboardType?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ControlledInputViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/ControlledInputViewNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,oBAAoB,EACpB,MAAM,EACP,MAAM,2CAA2C,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;CAE1B;AAED,MAAM,WAAW,SAAS;CAEzB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;IAC/D,OAAO,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IACvE,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;CACvE;AAED,eAAO,MAAM,QAAQ,EAAE,cAErB,CAAC;;AAEH,wBAA0E"}
|
|
1
|
+
{"version":3,"file":"ControlledInputViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/ControlledInputViewNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,oBAAoB,EACpB,MAAM,EACP,MAAM,2CAA2C,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;CAE1B;AAED,MAAM,WAAW,SAAS;CAEzB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,UAAU,CAAC;IAClC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;IAC/D,OAAO,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IACvE,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;CACvE;AAED,eAAO,MAAM,QAAQ,EAAE,cAErB,CAAC;;AAEH,wBAA0E"}
|
|
@@ -4,11 +4,11 @@ export interface ControlledInputViewRef {
|
|
|
4
4
|
blur: () => void;
|
|
5
5
|
focus: () => void;
|
|
6
6
|
}
|
|
7
|
-
type ForwardedTextInputProps = Pick<TextInputProps, 'autoComplete' | 'autoCapitalize' | 'keyboardType' | 'returnKeyType'>;
|
|
7
|
+
type ForwardedTextInputProps = Pick<TextInputProps, 'autoComplete' | 'autoCapitalize' | 'keyboardType' | 'returnKeyType' | 'placeholder' | 'placeholderTextColor' | 'selectionColor'>;
|
|
8
8
|
export type ControlledInputViewProps = Omit<NativeProps, 'inputStyle' | 'onTextChange' | keyof ForwardedTextInputProps> & ForwardedTextInputProps & {
|
|
9
9
|
onTextChange?: (value: string) => void;
|
|
10
10
|
};
|
|
11
|
-
export declare const ControlledInputView: import("react").NamedExoticComponent<Omit<NativeProps, "autoComplete" | "autoCapitalize" | "keyboardType" | "returnKeyType" | "inputStyle" | "onTextChange"> & ForwardedTextInputProps & {
|
|
11
|
+
export declare const ControlledInputView: import("react").NamedExoticComponent<Omit<NativeProps, "placeholder" | "placeholderTextColor" | "selectionColor" | "autoComplete" | "autoCapitalize" | "keyboardType" | "returnKeyType" | "inputStyle" | "onTextChange"> & ForwardedTextInputProps & {
|
|
12
12
|
onTextChange?: (value: string) => void;
|
|
13
13
|
} & import("react").RefAttributes<ControlledInputViewRef>>;
|
|
14
14
|
export * from './ControlledInputViewNativeComponent';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,cAAc,EAGpB,MAAM,cAAc,CAAC;AAItB,OAA2C,EACzC,KAAK,WAAW,EAEjB,MAAM,sCAAsC,CAAC;AAE9C,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,KAAK,uBAAuB,GAAG,IAAI,CACjC,cAAc,EACZ,cAAc,GACd,gBAAgB,GAChB,cAAc,GACd,eAAe,GACf,aAAa,GACb,sBAAsB,GACtB,gBAAgB,CACnB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,WAAW,EACX,YAAY,GAAG,cAAc,GAAG,MAAM,uBAAuB,CAC9D,GACC,uBAAuB,GAAG;IACxB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAsCJ,eAAO,MAAM,mBAAmB;mBAvCb,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;0DA0KzC,CAAC;AAIF,cAAc,sCAAsC,CAAC"}
|
package/package.json
CHANGED
|
@@ -38,6 +38,9 @@ export interface InputStyle {
|
|
|
38
38
|
|
|
39
39
|
export interface NativeProps extends ViewProps {
|
|
40
40
|
value?: string;
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
placeholderTextColor?: ColorValue;
|
|
43
|
+
selectionColor?: ColorValue;
|
|
41
44
|
autoComplete?: string;
|
|
42
45
|
autoCapitalize?: string;
|
|
43
46
|
keyboardType?: string;
|
package/src/index.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
forwardRef,
|
|
3
3
|
memo,
|
|
4
4
|
useImperativeHandle,
|
|
5
|
+
useLayoutEffect,
|
|
5
6
|
useRef,
|
|
6
7
|
type ElementRef,
|
|
7
8
|
} from 'react';
|
|
@@ -13,8 +14,10 @@ import {
|
|
|
13
14
|
type ViewStyle,
|
|
14
15
|
type TextStyle,
|
|
15
16
|
} from 'react-native';
|
|
17
|
+
// TextInputState is not exported from the public react-native package.
|
|
18
|
+
// eslint-disable-next-line @react-native/no-deep-imports -- integrate with ScrollView keyboard dismissal
|
|
19
|
+
import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
|
|
16
20
|
import ControlledInputViewNativeComponent, {
|
|
17
|
-
Commands,
|
|
18
21
|
type NativeProps,
|
|
19
22
|
type TextChangeEvent,
|
|
20
23
|
} from './ControlledInputViewNativeComponent';
|
|
@@ -26,7 +29,13 @@ export interface ControlledInputViewRef {
|
|
|
26
29
|
|
|
27
30
|
type ForwardedTextInputProps = Pick<
|
|
28
31
|
TextInputProps,
|
|
29
|
-
|
|
32
|
+
| 'autoComplete'
|
|
33
|
+
| 'autoCapitalize'
|
|
34
|
+
| 'keyboardType'
|
|
35
|
+
| 'returnKeyType'
|
|
36
|
+
| 'placeholder'
|
|
37
|
+
| 'placeholderTextColor'
|
|
38
|
+
| 'selectionColor'
|
|
30
39
|
>;
|
|
31
40
|
|
|
32
41
|
export type ControlledInputViewProps = Omit<
|
|
@@ -37,6 +46,13 @@ export type ControlledInputViewProps = Omit<
|
|
|
37
46
|
onTextChange?: (value: string) => void;
|
|
38
47
|
};
|
|
39
48
|
|
|
49
|
+
type ControlledInputFocusEvent = Parameters<
|
|
50
|
+
NonNullable<NativeProps['onFocus']>
|
|
51
|
+
>[0];
|
|
52
|
+
type ControlledInputBlurEvent = Parameters<
|
|
53
|
+
NonNullable<NativeProps['onBlur']>
|
|
54
|
+
>[0];
|
|
55
|
+
|
|
40
56
|
// All style props that Android handles via Compose instead of the native View layer
|
|
41
57
|
const androidComposeHandledKeys = [
|
|
42
58
|
'color',
|
|
@@ -68,10 +84,44 @@ function resolveAndroidComposeViewPadding(flat: Record<string, any>) {
|
|
|
68
84
|
|
|
69
85
|
export const ControlledInputView = memo(
|
|
70
86
|
forwardRef<ControlledInputViewRef, ControlledInputViewProps>(
|
|
71
|
-
(
|
|
87
|
+
(
|
|
88
|
+
{
|
|
89
|
+
style,
|
|
90
|
+
onTextChange,
|
|
91
|
+
onFocus,
|
|
92
|
+
onBlur,
|
|
93
|
+
selectionColor,
|
|
94
|
+
placeholderTextColor,
|
|
95
|
+
...rest
|
|
96
|
+
},
|
|
97
|
+
ref
|
|
98
|
+
) => {
|
|
72
99
|
const nativeRef =
|
|
73
100
|
useRef<ElementRef<typeof ControlledInputViewNativeComponent>>(null);
|
|
74
101
|
|
|
102
|
+
const isNativePlatform =
|
|
103
|
+
Platform.OS === 'ios' || Platform.OS === 'android';
|
|
104
|
+
|
|
105
|
+
useLayoutEffect(() => {
|
|
106
|
+
if (!isNativePlatform) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const node = nativeRef.current;
|
|
111
|
+
if (node == null) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
TextInputState.registerInput(node);
|
|
116
|
+
|
|
117
|
+
return () => {
|
|
118
|
+
TextInputState.unregisterInput(node);
|
|
119
|
+
if (TextInputState.currentlyFocusedInput() === node) {
|
|
120
|
+
TextInputState.blurTextInput(node);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}, [isNativePlatform]);
|
|
124
|
+
|
|
75
125
|
const flattenedStyle = (StyleSheet.flatten(style) ?? {}) as TextStyle;
|
|
76
126
|
|
|
77
127
|
let viewStyle: ViewStyle;
|
|
@@ -123,27 +173,41 @@ export const ControlledInputView = memo(
|
|
|
123
173
|
}
|
|
124
174
|
};
|
|
125
175
|
|
|
176
|
+
const handleFocus = (e: ControlledInputFocusEvent) => {
|
|
177
|
+
if (isNativePlatform) {
|
|
178
|
+
TextInputState.focusInput(nativeRef.current);
|
|
179
|
+
}
|
|
180
|
+
onFocus?.(e);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const handleBlur = (e: ControlledInputBlurEvent) => {
|
|
184
|
+
if (isNativePlatform) {
|
|
185
|
+
TextInputState.blurInput(nativeRef.current);
|
|
186
|
+
}
|
|
187
|
+
onBlur?.(e);
|
|
188
|
+
};
|
|
189
|
+
|
|
126
190
|
useImperativeHandle(ref, () => ({
|
|
127
191
|
blur: () => {
|
|
128
|
-
if (!nativeRef.current) return;
|
|
129
|
-
|
|
130
|
-
Commands.blur(nativeRef.current);
|
|
131
|
-
}
|
|
192
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
193
|
+
TextInputState.blurTextInput(nativeRef.current);
|
|
132
194
|
},
|
|
133
195
|
focus: () => {
|
|
134
|
-
if (!nativeRef.current) return;
|
|
135
|
-
|
|
136
|
-
Commands.focus(nativeRef.current);
|
|
137
|
-
}
|
|
196
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
197
|
+
TextInputState.focusTextInput(nativeRef.current);
|
|
138
198
|
},
|
|
139
199
|
}));
|
|
140
200
|
|
|
141
201
|
return (
|
|
142
202
|
<ControlledInputViewNativeComponent
|
|
143
203
|
{...rest}
|
|
204
|
+
placeholderTextColor={placeholderTextColor}
|
|
205
|
+
selectionColor={selectionColor}
|
|
144
206
|
style={viewStyle}
|
|
145
207
|
inputStyle={inputStyle}
|
|
146
208
|
onTextChange={handleTextChange}
|
|
209
|
+
onFocus={handleFocus}
|
|
210
|
+
onBlur={handleBlur}
|
|
147
211
|
ref={nativeRef}
|
|
148
212
|
/>
|
|
149
213
|
);
|
|
@@ -19,3 +19,19 @@ declare module 'react-native/Libraries/Utilities/codegenNativeComponent' {
|
|
|
19
19
|
componentName: string
|
|
20
20
|
): HostComponent<T>;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
declare module 'react-native/Libraries/Components/TextInput/TextInputState' {
|
|
24
|
+
import type { HostInstance } from 'react-native';
|
|
25
|
+
|
|
26
|
+
const TextInputState: {
|
|
27
|
+
registerInput(textField: HostInstance): void;
|
|
28
|
+
unregisterInput(textField: HostInstance): void;
|
|
29
|
+
focusInput(textField: HostInstance | null): void;
|
|
30
|
+
blurInput(textField: HostInstance | null): void;
|
|
31
|
+
focusTextInput(textField: HostInstance | null): void;
|
|
32
|
+
blurTextInput(textField: HostInstance | null): void;
|
|
33
|
+
currentlyFocusedInput(): HostInstance | null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default TextInputState;
|
|
37
|
+
}
|