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 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 on focus. |
72
- | `onBlur` | `() => void` | Called on blur. |
73
- | `style` | `StyleProp<ViewStyle>` | Input styles. Same public API on iOS and Android, with platform-specific internal handling. |
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
- Box(
141
- modifier = Modifier
142
- .fillMaxSize()
143
- .clip(shape)
144
- .background(backgroundColor)
145
- .border(borderWidth, borderColor, shape),
146
- ) {
147
- BasicTextField(
148
- state,
149
- inputTransformation = InputTransformation.byValue { _, proposed ->
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
- .padding(
156
- start = paddingLeft,
157
- top = paddingTop,
158
- end = paddingRight,
159
- bottom = paddingBottom,
160
- )
161
- .onGloballyPositioned {
162
- autofillNode.boundingBox = it.boundsInWindow()
163
- }
164
- .focusRequester(focusRequester),
165
- textStyle = TextStyle(
166
- color = textColor,
167
- fontSize = fontSize,
168
- fontFamily = fontFamily,
169
- ),
170
- keyboardOptions = KeyboardOptions(
171
- capitalization = toComposeCapitalization(autoCapitalizeValue),
172
- keyboardType = toComposeKeyboardType(keyboardTypeValue),
173
- imeAction = toComposeImeAction(returnKeyTypeValue),
174
- ),
175
- interactionSource = interactionSource,
176
- decorator = { innerTextField ->
177
- Box(
178
- modifier = Modifier.fillMaxSize(),
179
- contentAlignment = Alignment.CenterStart,
180
- ) {
181
- innerTextField()
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;
@@ -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
- import ControlledInputViewNativeComponent, { Commands } from './ControlledInputViewNativeComponent';
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
- if (Platform.OS === 'ios' || Platform.OS === 'android') {
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
- if (Platform.OS === 'ios' || Platform.OS === 'android') {
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
  }));
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","memo","useImperativeHandle","useRef","Platform","processColor","StyleSheet","ControlledInputViewNativeComponent","Commands","jsx","_jsx","androidComposeHandledKeys","resolveAndroidComposeViewPadding","flat","padding","paddingTop","paddingVertical","paddingBottom","paddingLeft","paddingHorizontal","paddingRight","ControlledInputView","style","onTextChange","rest","ref","nativeRef","flattenedStyle","flatten","viewStyle","inputStyle","OS","Object","fromEntries","entries","filter","k","includes","hasPadding","some","v","color","fontSize","fontFamily","borderWidth","borderRadius","borderColor","backgroundColor","iosViewStyle","hasTextStyle","undefined","handleTextChange","e","nativeEvent","value","blur","current","focus","displayName"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
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":"AAOA,OAAO,EAIL,KAAK,cAAc,EAGpB,MAAM,cAAc,CAAC;AACtB,OAA2C,EAEzC,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,EACd,cAAc,GAAG,gBAAgB,GAAG,cAAc,GAAG,eAAe,CACrE,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;AA+BJ,eAAO,MAAM,mBAAmB;mBAhCb,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;0DAmHzC,CAAC;AAIF,cAAc,sCAAsC,CAAC"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-controlled-input",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "React Native Controlled Inputative Controlled Input",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -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
- 'autoComplete' | 'autoCapitalize' | 'keyboardType' | 'returnKeyType'
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
- ({ style, onTextChange, ...rest }, ref) => {
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
- if (Platform.OS === 'ios' || Platform.OS === 'android') {
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
- if (Platform.OS === 'ios' || Platform.OS === 'android') {
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
+ }