react-native-controlled-input 0.8.0 → 0.9.1
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 +75 -12
- package/android/src/main/java/com/controlledinput/ControlledInputView.kt +6 -4
- package/android/src/main/java/com/controlledinput/ControlledInputViewManager.kt +1 -1
- package/android/src/main/java/com/controlledinput/JetpackComposeView.kt +37 -21
- package/ios/ControlledInputView.mm +22 -26
- package/ios/RNControlledInput.swift +10 -35
- package/lib/module/ControlledInputViewNativeComponent.ts +2 -2
- package/lib/module/index.js +54 -19
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/ControlledInputViewNativeComponent.d.ts +2 -2
- package/lib/typescript/src/ControlledInputViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ControlledInputViewNativeComponent.ts +2 -2
- package/src/index.tsx +92 -33
package/README.md
CHANGED
|
@@ -1,32 +1,95 @@
|
|
|
1
1
|
# react-native-controlled-input
|
|
2
2
|
|
|
3
|
-
React Native
|
|
3
|
+
A controlled React Native input that lets you format and constrain the value exactly how you want in JS, while keeping the displayed text in sync without invalid characters flashing in the field.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Problem
|
|
6
6
|
|
|
7
|
+
With a regular controlled `TextInput`, native input is applied first, then JS receives the change, filters it, and sends the next `value` back.
|
|
8
|
+
|
|
9
|
+
That means invalid characters can still flash in the field for a moment.
|
|
10
|
+
|
|
11
|
+
`react-native-controlled-input` is built for this exact case: you decide what text is valid, and the displayed value stays driven by `value`.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
7
14
|
|
|
8
15
|
```sh
|
|
9
16
|
npm install react-native-controlled-input
|
|
10
17
|
```
|
|
11
18
|
|
|
19
|
+
Requires React Native New Architecture / Fabric.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { useRef, useState } from 'react';
|
|
25
|
+
import { StyleSheet } from 'react-native';
|
|
26
|
+
import {
|
|
27
|
+
ControlledInputView,
|
|
28
|
+
type ControlledInputViewRef,
|
|
29
|
+
} from 'react-native-controlled-input';
|
|
30
|
+
|
|
31
|
+
export function Example() {
|
|
32
|
+
const [value, setValue] = useState('');
|
|
33
|
+
const inputRef = useRef<ControlledInputViewRef>(null);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<ControlledInputView
|
|
37
|
+
ref={inputRef}
|
|
38
|
+
value={value}
|
|
39
|
+
onTextChange={(text) => setValue(text.replace(/\d/g, ''))}
|
|
40
|
+
style={styles.input}
|
|
41
|
+
onFocus={() => {}}
|
|
42
|
+
onBlur={() => {}}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const styles = StyleSheet.create({
|
|
48
|
+
input: {
|
|
49
|
+
height: 48,
|
|
50
|
+
borderWidth: 1,
|
|
51
|
+
borderColor: '#ccc',
|
|
52
|
+
borderRadius: 8,
|
|
53
|
+
paddingHorizontal: 12,
|
|
54
|
+
fontSize: 16,
|
|
55
|
+
color: '#111',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
inputRef.current?.focus();
|
|
62
|
+
inputRef.current?.blur();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Props
|
|
12
66
|
|
|
13
|
-
|
|
67
|
+
| Prop | Type | Description |
|
|
68
|
+
|------|------|-------------|
|
|
69
|
+
| `value` | `string` | Current input value. |
|
|
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. |
|
|
14
74
|
|
|
75
|
+
## Style support
|
|
15
76
|
|
|
16
|
-
|
|
17
|
-
import { ControlledInputView } from "react-native-controlled-input";
|
|
77
|
+
The same `style` API is supported on both iOS and Android.
|
|
18
78
|
|
|
19
|
-
|
|
79
|
+
Commonly used supported styles:
|
|
20
80
|
|
|
21
|
-
|
|
22
|
-
|
|
81
|
+
- `color`, `fontSize`, `fontFamily`
|
|
82
|
+
- `padding`, `paddingVertical`, `paddingHorizontal`
|
|
83
|
+
- `paddingTop`, `paddingBottom`, `paddingLeft`, `paddingRight`, `paddingStart`, `paddingEnd`
|
|
84
|
+
- `borderWidth`, `borderRadius`, `borderColor`, `backgroundColor`
|
|
85
|
+
- layout styles like `width`, `height`, `margin`, `flex`
|
|
23
86
|
|
|
87
|
+
Implementation differs internally between platforms, but usage is the same for library consumers.
|
|
24
88
|
|
|
25
|
-
##
|
|
89
|
+
## Ref
|
|
26
90
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- [Code of conduct](CODE_OF_CONDUCT.md)
|
|
91
|
+
- `focus()`
|
|
92
|
+
- `blur()`
|
|
30
93
|
|
|
31
94
|
## License
|
|
32
95
|
|
|
@@ -56,17 +56,19 @@ class ControlledInputView : LinearLayout {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
private fun configureComponent(context: Context) {
|
|
59
|
+
setBackgroundColor(android.graphics.Color.TRANSPARENT)
|
|
59
60
|
|
|
60
61
|
layoutParams = LayoutParams(
|
|
61
|
-
LayoutParams.
|
|
62
|
-
LayoutParams.
|
|
62
|
+
LayoutParams.MATCH_PARENT,
|
|
63
|
+
LayoutParams.MATCH_PARENT
|
|
63
64
|
)
|
|
64
65
|
|
|
65
66
|
ComposeView(context).also {
|
|
66
67
|
it.layoutParams = LayoutParams(
|
|
67
|
-
LayoutParams.
|
|
68
|
-
LayoutParams.
|
|
68
|
+
LayoutParams.MATCH_PARENT,
|
|
69
|
+
LayoutParams.MATCH_PARENT
|
|
69
70
|
)
|
|
71
|
+
it.setBackgroundColor(android.graphics.Color.TRANSPARENT)
|
|
70
72
|
|
|
71
73
|
viewModel = JetpackComposeViewModel()
|
|
72
74
|
|
|
@@ -47,7 +47,6 @@ class ControlledInputViewManager : SimpleViewManager<ControlledInputView>(),
|
|
|
47
47
|
color = if (inputStyle.hasKey("color")) inputStyle.getString("color") else null,
|
|
48
48
|
fontSize = if (inputStyle.hasKey("fontSize")) inputStyle.getDouble("fontSize") else null,
|
|
49
49
|
fontFamily = if (inputStyle.hasKey("fontFamily")) inputStyle.getString("fontFamily") else null,
|
|
50
|
-
height = if (inputStyle.hasKey("height")) inputStyle.getDouble("height") else null,
|
|
51
50
|
paddingTop = if (inputStyle.hasKey("paddingTop")) inputStyle.getDouble("paddingTop") else null,
|
|
52
51
|
paddingBottom = if (inputStyle.hasKey("paddingBottom")) inputStyle.getDouble("paddingBottom") else null,
|
|
53
52
|
paddingLeft = if (inputStyle.hasKey("paddingLeft")) inputStyle.getDouble("paddingLeft") else null,
|
|
@@ -55,6 +54,7 @@ class ControlledInputViewManager : SimpleViewManager<ControlledInputView>(),
|
|
|
55
54
|
borderWidth = if (inputStyle.hasKey("borderWidth")) inputStyle.getDouble("borderWidth") else null,
|
|
56
55
|
borderRadius = if (inputStyle.hasKey("borderRadius")) inputStyle.getDouble("borderRadius") else null,
|
|
57
56
|
borderColor = if (inputStyle.hasKey("borderColor")) inputStyle.getString("borderColor") else null,
|
|
57
|
+
backgroundColor = if (inputStyle.hasKey("backgroundColor")) inputStyle.getString("backgroundColor") else null,
|
|
58
58
|
)
|
|
59
59
|
}
|
|
60
60
|
view.viewModel.setInputStyle(style)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
package com.controlledinput
|
|
2
2
|
|
|
3
|
+
import androidx.compose.foundation.background
|
|
3
4
|
import androidx.compose.foundation.border
|
|
4
|
-
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
5
5
|
import androidx.compose.foundation.layout.Box
|
|
6
|
-
import androidx.compose.ui.draw.clip
|
|
7
|
-
import androidx.compose.foundation.layout.PaddingValues
|
|
8
6
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
9
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
10
|
-
import androidx.compose.foundation.layout.height
|
|
11
7
|
import androidx.compose.foundation.layout.padding
|
|
8
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
9
|
+
import androidx.compose.ui.Alignment
|
|
10
|
+
import androidx.compose.ui.draw.clip
|
|
12
11
|
import androidx.compose.foundation.text.BasicTextField
|
|
12
|
+
import androidx.compose.ui.unit.dp
|
|
13
13
|
import androidx.compose.foundation.text.input.InputTransformation
|
|
14
14
|
import androidx.compose.foundation.text.input.TextFieldState
|
|
15
15
|
import androidx.compose.foundation.text.input.byValue
|
|
@@ -29,7 +29,6 @@ import androidx.compose.ui.graphics.Color
|
|
|
29
29
|
import androidx.compose.ui.platform.LocalContext
|
|
30
30
|
import androidx.compose.ui.text.TextStyle
|
|
31
31
|
import androidx.compose.ui.text.font.FontFamily
|
|
32
|
-
import androidx.compose.ui.unit.dp
|
|
33
32
|
import androidx.compose.ui.unit.sp
|
|
34
33
|
import androidx.lifecycle.ViewModel
|
|
35
34
|
import com.facebook.react.bridge.Arguments
|
|
@@ -42,7 +41,6 @@ data class InputStyle(
|
|
|
42
41
|
val color: String? = null,
|
|
43
42
|
val fontSize: Double? = null,
|
|
44
43
|
val fontFamily: String? = null,
|
|
45
|
-
val height: Double? = null,
|
|
46
44
|
val paddingTop: Double? = null,
|
|
47
45
|
val paddingBottom: Double? = null,
|
|
48
46
|
val paddingLeft: Double? = null,
|
|
@@ -50,6 +48,7 @@ data class InputStyle(
|
|
|
50
48
|
val borderWidth: Double? = null,
|
|
51
49
|
val borderRadius: Double? = null,
|
|
52
50
|
val borderColor: String? = null,
|
|
51
|
+
val backgroundColor: String? = null,
|
|
53
52
|
)
|
|
54
53
|
|
|
55
54
|
@Composable
|
|
@@ -96,23 +95,27 @@ fun JetpackComposeView(
|
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
97
|
}
|
|
99
|
-
|
|
100
|
-
val
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
bottom = style?.paddingBottom?.dp ?: 0.dp,
|
|
105
|
-
)
|
|
98
|
+
|
|
99
|
+
val paddingTop = style?.paddingTop?.dp ?: 0.dp
|
|
100
|
+
val paddingBottom = style?.paddingBottom?.dp ?: 0.dp
|
|
101
|
+
val paddingLeft = style?.paddingLeft?.dp ?: 0.dp
|
|
102
|
+
val paddingRight = style?.paddingRight?.dp ?: 0.dp
|
|
106
103
|
val borderWidth = style?.borderWidth?.dp ?: 0.dp
|
|
107
104
|
val borderRadius = style?.borderRadius?.dp ?: 0.dp
|
|
108
|
-
val borderColor = style?.borderColor
|
|
105
|
+
val borderColor = style?.borderColor
|
|
106
|
+
?.let { Color(android.graphics.Color.parseColor(it)) }
|
|
107
|
+
?: Color.Transparent
|
|
108
|
+
val backgroundColor = style?.backgroundColor
|
|
109
|
+
?.let { Color(android.graphics.Color.parseColor(it)) }
|
|
110
|
+
?: Color.Transparent
|
|
111
|
+
val shape = RoundedCornerShape(borderRadius)
|
|
109
112
|
|
|
110
113
|
Box(
|
|
111
114
|
modifier = Modifier
|
|
112
|
-
.
|
|
113
|
-
.
|
|
114
|
-
.
|
|
115
|
-
.border(borderWidth, borderColor,
|
|
115
|
+
.fillMaxSize()
|
|
116
|
+
.clip(shape)
|
|
117
|
+
.background(backgroundColor)
|
|
118
|
+
.border(borderWidth, borderColor, shape),
|
|
116
119
|
) {
|
|
117
120
|
BasicTextField(
|
|
118
121
|
state,
|
|
@@ -121,8 +124,13 @@ fun JetpackComposeView(
|
|
|
121
124
|
proposed
|
|
122
125
|
},
|
|
123
126
|
modifier = Modifier
|
|
124
|
-
.
|
|
125
|
-
.padding(
|
|
127
|
+
.fillMaxSize()
|
|
128
|
+
.padding(
|
|
129
|
+
start = paddingLeft,
|
|
130
|
+
top = paddingTop,
|
|
131
|
+
end = paddingRight,
|
|
132
|
+
bottom = paddingBottom,
|
|
133
|
+
)
|
|
126
134
|
.focusRequester(focusRequester),
|
|
127
135
|
textStyle = TextStyle(
|
|
128
136
|
color = textColor,
|
|
@@ -130,6 +138,14 @@ fun JetpackComposeView(
|
|
|
130
138
|
fontFamily = fontFamily,
|
|
131
139
|
),
|
|
132
140
|
interactionSource = interactionSource,
|
|
141
|
+
decorator = { innerTextField ->
|
|
142
|
+
Box(
|
|
143
|
+
modifier = Modifier.fillMaxSize(),
|
|
144
|
+
contentAlignment = Alignment.CenterStart,
|
|
145
|
+
) {
|
|
146
|
+
innerTextField()
|
|
147
|
+
}
|
|
148
|
+
},
|
|
133
149
|
)
|
|
134
150
|
}
|
|
135
151
|
}
|
|
@@ -52,44 +52,20 @@ using namespace facebook::react;
|
|
|
52
52
|
_inputView.value = [NSString stringWithUTF8String:newViewProps.value.c_str()];
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// Update inputStyle props
|
|
56
55
|
const auto &style = newViewProps.inputStyle;
|
|
57
56
|
const auto &oldStyle = oldViewProps.inputStyle;
|
|
58
57
|
|
|
59
58
|
if (oldStyle.color != style.color) {
|
|
60
59
|
_inputView.textColor = RCTUIColorFromSharedColor(style.color);
|
|
61
60
|
}
|
|
62
|
-
|
|
61
|
+
|
|
63
62
|
if (oldStyle.fontSize != style.fontSize) {
|
|
64
63
|
_inputView.fontSize = style.fontSize;
|
|
65
64
|
}
|
|
66
|
-
|
|
65
|
+
|
|
67
66
|
if (oldStyle.fontFamily != style.fontFamily) {
|
|
68
67
|
_inputView.fontFamily = style.fontFamily.empty() ? nil : [NSString stringWithUTF8String:style.fontFamily.c_str()];
|
|
69
68
|
}
|
|
70
|
-
|
|
71
|
-
if (oldStyle.height != style.height) {
|
|
72
|
-
_inputView.inputHeight = style.height;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (oldStyle.paddingTop != style.paddingTop ||
|
|
76
|
-
oldStyle.paddingBottom != style.paddingBottom ||
|
|
77
|
-
oldStyle.paddingLeft != style.paddingLeft ||
|
|
78
|
-
oldStyle.paddingRight != style.paddingRight) {
|
|
79
|
-
_inputView.padding = UIEdgeInsetsMake(style.paddingTop, style.paddingLeft, style.paddingBottom, style.paddingRight);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (oldStyle.borderWidth != style.borderWidth) {
|
|
83
|
-
_inputView.borderWidth = style.borderWidth;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (oldStyle.borderRadius != style.borderRadius) {
|
|
87
|
-
_inputView.borderRadius = style.borderRadius;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (oldStyle.borderColor != style.borderColor) {
|
|
91
|
-
_inputView.borderColor = RCTUIColorFromSharedColor(style.borderColor);
|
|
92
|
-
}
|
|
93
69
|
|
|
94
70
|
[super updateProps:props oldProps:oldProps];
|
|
95
71
|
}
|
|
@@ -125,4 +101,24 @@ using namespace facebook::react;
|
|
|
125
101
|
});
|
|
126
102
|
}
|
|
127
103
|
|
|
104
|
+
- (void)controlledInputDidFocus:(RNControlledInput *)input
|
|
105
|
+
{
|
|
106
|
+
if (_eventEmitter == nullptr) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const auto eventEmitter = std::static_pointer_cast<const ControlledInputViewEventEmitter>(_eventEmitter);
|
|
111
|
+
eventEmitter->onFocus(ControlledInputViewEventEmitter::OnFocus {});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
- (void)controlledInputDidBlur:(RNControlledInput *)input
|
|
115
|
+
{
|
|
116
|
+
if (_eventEmitter == nullptr) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const auto eventEmitter = std::static_pointer_cast<const ControlledInputViewEventEmitter>(_eventEmitter);
|
|
121
|
+
eventEmitter->onBlur(ControlledInputViewEventEmitter::OnBlur {});
|
|
122
|
+
}
|
|
123
|
+
|
|
128
124
|
@end
|
|
@@ -2,6 +2,8 @@ import UIKit
|
|
|
2
2
|
|
|
3
3
|
@objc public protocol RNControlledInputDelegate: AnyObject {
|
|
4
4
|
func controlledInputDidChangeText(_ input: RNControlledInput, value: String)
|
|
5
|
+
func controlledInputDidFocus(_ input: RNControlledInput)
|
|
6
|
+
func controlledInputDidBlur(_ input: RNControlledInput)
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
@objc(RNControlledInput)
|
|
@@ -30,26 +32,6 @@ public class RNControlledInput: UIView, UITextFieldDelegate {
|
|
|
30
32
|
didSet { applyFont() }
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
@objc public var inputHeight: CGFloat = 0 {
|
|
34
|
-
didSet { invalidateIntrinsicContentSize() }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
@objc public var padding: UIEdgeInsets = .zero {
|
|
38
|
-
didSet { applyPadding() }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
@objc public var borderWidth: CGFloat = 0 {
|
|
42
|
-
didSet { layer.borderWidth = borderWidth }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@objc public var borderRadius: CGFloat = 0 {
|
|
46
|
-
didSet { layer.cornerRadius = borderRadius }
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
@objc public var borderColor: UIColor? {
|
|
50
|
-
didSet { layer.borderColor = borderColor?.cgColor }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
35
|
public override var canBecomeFirstResponder: Bool { true }
|
|
54
36
|
|
|
55
37
|
@objc public func focus() {
|
|
@@ -85,6 +67,14 @@ public class RNControlledInput: UIView, UITextFieldDelegate {
|
|
|
85
67
|
applyFont()
|
|
86
68
|
}
|
|
87
69
|
|
|
70
|
+
public func textFieldDidBeginEditing(_ textField: UITextField) {
|
|
71
|
+
delegate?.controlledInputDidFocus(self)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public func textFieldDidEndEditing(_ textField: UITextField) {
|
|
75
|
+
delegate?.controlledInputDidBlur(self)
|
|
76
|
+
}
|
|
77
|
+
|
|
88
78
|
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
|
89
79
|
let currentText = textField.text ?? ""
|
|
90
80
|
guard let stringRange = Range(range, in: currentText) else { return true }
|
|
@@ -102,19 +92,4 @@ public class RNControlledInput: UIView, UITextFieldDelegate {
|
|
|
102
92
|
textField.font = UIFont.systemFont(ofSize: fontSize)
|
|
103
93
|
}
|
|
104
94
|
}
|
|
105
|
-
|
|
106
|
-
private func applyPadding() {
|
|
107
|
-
// UITextField doesn't have built-in edge insets — wrap with container views
|
|
108
|
-
let leftView = UIView(frame: CGRect(x: 0, y: 0, width: padding.left, height: 1))
|
|
109
|
-
let rightView = UIView(frame: CGRect(x: 0, y: 0, width: padding.right, height: 1))
|
|
110
|
-
textField.leftView = leftView
|
|
111
|
-
textField.leftViewMode = .always
|
|
112
|
-
textField.rightView = rightView
|
|
113
|
-
textField.rightViewMode = .always
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
public override func layoutSubviews() {
|
|
117
|
-
super.layoutSubviews()
|
|
118
|
-
layer.borderColor = borderColor?.cgColor
|
|
119
|
-
}
|
|
120
95
|
}
|
|
@@ -26,14 +26,14 @@ interface InputStyle {
|
|
|
26
26
|
color?: ColorValue;
|
|
27
27
|
fontSize?: Double;
|
|
28
28
|
fontFamily?: string;
|
|
29
|
-
height?: Double;
|
|
30
29
|
paddingTop?: Double;
|
|
31
30
|
paddingBottom?: Double;
|
|
32
31
|
paddingLeft?: Double;
|
|
33
32
|
paddingRight?: Double;
|
|
34
33
|
borderWidth?: Double;
|
|
35
34
|
borderRadius?: Double;
|
|
36
|
-
borderColor?:
|
|
35
|
+
borderColor?: string;
|
|
36
|
+
backgroundColor?: string;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export interface NativeProps extends ViewProps {
|
package/lib/module/index.js
CHANGED
|
@@ -1,41 +1,76 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { forwardRef, useImperativeHandle, useRef } from 'react';
|
|
4
|
-
import { Platform, processColor } from 'react-native';
|
|
4
|
+
import { Platform, processColor, StyleSheet } from 'react-native';
|
|
5
5
|
import ControlledInputViewNativeComponent, { Commands } from './ControlledInputViewNativeComponent';
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
-
|
|
7
|
+
// All style props that Android handles via Compose instead of the native View layer
|
|
8
|
+
const ANDROID_HANDLED_KEYS = ['color', 'fontSize', 'fontFamily', 'padding', 'paddingVertical', 'paddingHorizontal', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingStart', 'paddingEnd', 'borderWidth', 'borderRadius', 'borderColor', 'backgroundColor'];
|
|
9
|
+
function resolveAndroidPadding(flat) {
|
|
10
|
+
const base = flat.padding ?? 0;
|
|
11
|
+
return {
|
|
12
|
+
paddingTop: flat.paddingTop ?? flat.paddingVertical ?? base,
|
|
13
|
+
paddingBottom: flat.paddingBottom ?? flat.paddingVertical ?? base,
|
|
14
|
+
paddingLeft: flat.paddingLeft ?? flat.paddingStart ?? flat.paddingHorizontal ?? base,
|
|
15
|
+
paddingRight: flat.paddingRight ?? flat.paddingEnd ?? flat.paddingHorizontal ?? base
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export const ControlledInputView = /*#__PURE__*/forwardRef(({
|
|
19
|
+
style,
|
|
20
|
+
onTextChange,
|
|
21
|
+
...rest
|
|
22
|
+
}, ref) => {
|
|
8
23
|
const nativeRef = useRef(null);
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
const flat = StyleSheet.flatten(style) ?? {};
|
|
25
|
+
let viewStyle;
|
|
26
|
+
let inputStyle;
|
|
27
|
+
if (Platform.OS === 'android') {
|
|
28
|
+
viewStyle = Object.fromEntries(Object.entries(flat).filter(([k]) => !ANDROID_HANDLED_KEYS.includes(k)));
|
|
29
|
+
const hasPadding = ANDROID_HANDLED_KEYS.slice(3, 12).some(k => flat[k] != null);
|
|
30
|
+
inputStyle = {
|
|
31
|
+
color: flat.color,
|
|
32
|
+
fontSize: flat.fontSize,
|
|
33
|
+
fontFamily: flat.fontFamily,
|
|
34
|
+
...(hasPadding ? resolveAndroidPadding(flat) : {}),
|
|
35
|
+
borderWidth: flat.borderWidth,
|
|
36
|
+
borderRadius: flat.borderRadius,
|
|
37
|
+
borderColor: flat.borderColor,
|
|
38
|
+
backgroundColor: flat.backgroundColor
|
|
39
|
+
};
|
|
40
|
+
} else {
|
|
41
|
+
const {
|
|
42
|
+
color,
|
|
43
|
+
fontSize,
|
|
44
|
+
fontFamily,
|
|
45
|
+
...iosRest
|
|
46
|
+
} = flat;
|
|
47
|
+
viewStyle = iosRest;
|
|
48
|
+
const hasTextStyle = color != null || fontSize != null || fontFamily != null;
|
|
49
|
+
inputStyle = hasTextStyle ? {
|
|
50
|
+
color: color != null ? processColor(color) : undefined,
|
|
51
|
+
fontSize,
|
|
52
|
+
fontFamily
|
|
53
|
+
} : undefined;
|
|
54
|
+
}
|
|
17
55
|
useImperativeHandle(ref, () => ({
|
|
18
56
|
blur: () => {
|
|
19
|
-
if (!nativeRef.current)
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
57
|
+
if (!nativeRef.current) return;
|
|
22
58
|
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
23
|
-
console.log(`[ControlledInputView] ${Platform.OS} blur command -> native`);
|
|
24
59
|
Commands.blur(nativeRef.current);
|
|
25
60
|
}
|
|
26
61
|
},
|
|
27
62
|
focus: () => {
|
|
28
|
-
if (!nativeRef.current)
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
63
|
+
if (!nativeRef.current) return;
|
|
31
64
|
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
32
|
-
console.log(`[ControlledInputView] ${Platform.OS} focus command -> native`);
|
|
33
65
|
Commands.focus(nativeRef.current);
|
|
34
66
|
}
|
|
35
67
|
}
|
|
36
68
|
}));
|
|
37
69
|
return /*#__PURE__*/_jsx(ControlledInputViewNativeComponent, {
|
|
38
|
-
...
|
|
70
|
+
...rest,
|
|
71
|
+
style: viewStyle,
|
|
72
|
+
inputStyle: inputStyle,
|
|
73
|
+
onTextChange: onTextChange ? e => onTextChange(e.nativeEvent.value) : undefined,
|
|
39
74
|
ref: nativeRef
|
|
40
75
|
});
|
|
41
76
|
});
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["forwardRef","useImperativeHandle","useRef","Platform","processColor","ControlledInputViewNativeComponent","Commands","jsx","_jsx","ControlledInputView","
|
|
1
|
+
{"version":3,"names":["forwardRef","useImperativeHandle","useRef","Platform","processColor","StyleSheet","ControlledInputViewNativeComponent","Commands","jsx","_jsx","ANDROID_HANDLED_KEYS","resolveAndroidPadding","flat","base","padding","paddingTop","paddingVertical","paddingBottom","paddingLeft","paddingStart","paddingHorizontal","paddingRight","paddingEnd","ControlledInputView","style","onTextChange","rest","ref","nativeRef","flatten","viewStyle","inputStyle","OS","Object","fromEntries","entries","filter","k","includes","hasPadding","slice","some","color","fontSize","fontFamily","borderWidth","borderRadius","borderColor","backgroundColor","iosRest","hasTextStyle","undefined","blur","current","focus","e","nativeEvent","value"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -11,14 +11,14 @@ interface InputStyle {
|
|
|
11
11
|
color?: ColorValue;
|
|
12
12
|
fontSize?: Double;
|
|
13
13
|
fontFamily?: string;
|
|
14
|
-
height?: Double;
|
|
15
14
|
paddingTop?: Double;
|
|
16
15
|
paddingBottom?: Double;
|
|
17
16
|
paddingLeft?: Double;
|
|
18
17
|
paddingRight?: Double;
|
|
19
18
|
borderWidth?: Double;
|
|
20
19
|
borderRadius?: Double;
|
|
21
|
-
borderColor?:
|
|
20
|
+
borderColor?: string;
|
|
21
|
+
backgroundColor?: string;
|
|
22
22
|
}
|
|
23
23
|
export interface NativeProps extends ViewProps {
|
|
24
24
|
value?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ControlledInputViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/ControlledInputViewNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,oBAAoB,EACpB,MAAM,EACP,MAAM,2CAA2C,CAAC;AAEnD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,UAAU;CAEnB;AAED,UAAU,SAAS;CAElB;AAED,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,
|
|
1
|
+
{"version":3,"file":"ControlledInputViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/ControlledInputViewNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,oBAAoB,EACpB,MAAM,EACP,MAAM,2CAA2C,CAAC;AAEnD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,UAAU;CAEnB;AAED,UAAU,SAAS;CAElB;AAED,UAAU,UAAU;IAClB,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,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"}
|
|
@@ -3,6 +3,11 @@ export interface ControlledInputViewRef {
|
|
|
3
3
|
blur: () => void;
|
|
4
4
|
focus: () => void;
|
|
5
5
|
}
|
|
6
|
-
export
|
|
6
|
+
export type ControlledInputViewProps = Omit<NativeProps, 'inputStyle' | 'onTextChange'> & {
|
|
7
|
+
onTextChange?: (value: string) => void;
|
|
8
|
+
};
|
|
9
|
+
export declare const ControlledInputView: import("react").ForwardRefExoticComponent<Omit<NativeProps, "inputStyle" | "onTextChange"> & {
|
|
10
|
+
onTextChange?: (value: string) => void;
|
|
11
|
+
} & import("react").RefAttributes<ControlledInputViewRef>>;
|
|
7
12
|
export * from './ControlledInputViewNativeComponent';
|
|
8
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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":"AAYA,OAA2C,EAEzC,KAAK,WAAW,EACjB,MAAM,sCAAsC,CAAC;AAE9C,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,WAAW,EACX,YAAY,GAAG,cAAc,CAC9B,GAAG;IACF,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAkCF,eAAO,MAAM,mBAAmB;mBAnCf,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;0DA2GtC,CAAC;AAEH,cAAc,sCAAsC,CAAC"}
|
package/package.json
CHANGED
|
@@ -26,14 +26,14 @@ interface InputStyle {
|
|
|
26
26
|
color?: ColorValue;
|
|
27
27
|
fontSize?: Double;
|
|
28
28
|
fontFamily?: string;
|
|
29
|
-
height?: Double;
|
|
30
29
|
paddingTop?: Double;
|
|
31
30
|
paddingBottom?: Double;
|
|
32
31
|
paddingLeft?: Double;
|
|
33
32
|
paddingRight?: Double;
|
|
34
33
|
borderWidth?: Double;
|
|
35
34
|
borderRadius?: Double;
|
|
36
|
-
borderColor?:
|
|
35
|
+
borderColor?: string;
|
|
36
|
+
backgroundColor?: string;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export interface NativeProps extends ViewProps {
|
package/src/index.tsx
CHANGED
|
@@ -4,7 +4,12 @@ import {
|
|
|
4
4
|
useRef,
|
|
5
5
|
type ElementRef,
|
|
6
6
|
} from 'react';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Platform,
|
|
9
|
+
processColor,
|
|
10
|
+
StyleSheet,
|
|
11
|
+
type ViewStyle,
|
|
12
|
+
} from 'react-native';
|
|
8
13
|
import ControlledInputViewNativeComponent, {
|
|
9
14
|
Commands,
|
|
10
15
|
type NativeProps,
|
|
@@ -15,52 +20,101 @@ export interface ControlledInputViewRef {
|
|
|
15
20
|
focus: () => void;
|
|
16
21
|
}
|
|
17
22
|
|
|
23
|
+
export type ControlledInputViewProps = Omit<
|
|
24
|
+
NativeProps,
|
|
25
|
+
'inputStyle' | 'onTextChange'
|
|
26
|
+
> & {
|
|
27
|
+
onTextChange?: (value: string) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// All style props that Android handles via Compose instead of the native View layer
|
|
31
|
+
const ANDROID_HANDLED_KEYS = [
|
|
32
|
+
'color',
|
|
33
|
+
'fontSize',
|
|
34
|
+
'fontFamily',
|
|
35
|
+
'padding',
|
|
36
|
+
'paddingVertical',
|
|
37
|
+
'paddingHorizontal',
|
|
38
|
+
'paddingTop',
|
|
39
|
+
'paddingBottom',
|
|
40
|
+
'paddingLeft',
|
|
41
|
+
'paddingRight',
|
|
42
|
+
'paddingStart',
|
|
43
|
+
'paddingEnd',
|
|
44
|
+
'borderWidth',
|
|
45
|
+
'borderRadius',
|
|
46
|
+
'borderColor',
|
|
47
|
+
'backgroundColor',
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
function resolveAndroidPadding(flat: Record<string, any>) {
|
|
51
|
+
const base = flat.padding ?? 0;
|
|
52
|
+
return {
|
|
53
|
+
paddingTop: flat.paddingTop ?? flat.paddingVertical ?? base,
|
|
54
|
+
paddingBottom: flat.paddingBottom ?? flat.paddingVertical ?? base,
|
|
55
|
+
paddingLeft:
|
|
56
|
+
flat.paddingLeft ?? flat.paddingStart ?? flat.paddingHorizontal ?? base,
|
|
57
|
+
paddingRight:
|
|
58
|
+
flat.paddingRight ?? flat.paddingEnd ?? flat.paddingHorizontal ?? base,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
18
62
|
export const ControlledInputView = forwardRef<
|
|
19
63
|
ControlledInputViewRef,
|
|
20
|
-
|
|
21
|
-
>((
|
|
64
|
+
ControlledInputViewProps
|
|
65
|
+
>(({ style, onTextChange, ...rest }, ref) => {
|
|
22
66
|
const nativeRef =
|
|
23
67
|
useRef<ElementRef<typeof ControlledInputViewNativeComponent>>(null);
|
|
24
|
-
|
|
25
|
-
|
|
68
|
+
|
|
69
|
+
const flat = (StyleSheet.flatten(style) ?? {}) as Record<string, any>;
|
|
70
|
+
|
|
71
|
+
let viewStyle: ViewStyle;
|
|
72
|
+
let inputStyle: Record<string, any> | undefined;
|
|
73
|
+
|
|
74
|
+
if (Platform.OS === 'android') {
|
|
75
|
+
viewStyle = Object.fromEntries(
|
|
76
|
+
Object.entries(flat).filter(([k]) => !ANDROID_HANDLED_KEYS.includes(k))
|
|
77
|
+
) as ViewStyle;
|
|
78
|
+
|
|
79
|
+
const hasPadding = ANDROID_HANDLED_KEYS.slice(3, 12).some(
|
|
80
|
+
(k) => flat[k] != null
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
inputStyle = {
|
|
84
|
+
color: flat.color,
|
|
85
|
+
fontSize: flat.fontSize,
|
|
86
|
+
fontFamily: flat.fontFamily,
|
|
87
|
+
...(hasPadding ? resolveAndroidPadding(flat) : {}),
|
|
88
|
+
borderWidth: flat.borderWidth,
|
|
89
|
+
borderRadius: flat.borderRadius,
|
|
90
|
+
borderColor: flat.borderColor,
|
|
91
|
+
backgroundColor: flat.backgroundColor,
|
|
92
|
+
};
|
|
93
|
+
} else {
|
|
94
|
+
const { color, fontSize, fontFamily, ...iosRest } = flat;
|
|
95
|
+
viewStyle = iosRest as ViewStyle;
|
|
96
|
+
|
|
97
|
+
const hasTextStyle =
|
|
98
|
+
color != null || fontSize != null || fontFamily != null;
|
|
99
|
+
inputStyle = hasTextStyle
|
|
26
100
|
? {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
color:
|
|
31
|
-
props.inputStyle.color == null
|
|
32
|
-
? props.inputStyle.color
|
|
33
|
-
: processColor(props.inputStyle.color),
|
|
34
|
-
borderColor:
|
|
35
|
-
props.inputStyle.borderColor == null
|
|
36
|
-
? props.inputStyle.borderColor
|
|
37
|
-
: processColor(props.inputStyle.borderColor),
|
|
38
|
-
},
|
|
101
|
+
color: color != null ? processColor(color) : undefined,
|
|
102
|
+
fontSize,
|
|
103
|
+
fontFamily,
|
|
39
104
|
}
|
|
40
|
-
:
|
|
105
|
+
: undefined;
|
|
106
|
+
}
|
|
41
107
|
|
|
42
108
|
useImperativeHandle(ref, () => ({
|
|
43
109
|
blur: () => {
|
|
44
|
-
if (!nativeRef.current)
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
110
|
+
if (!nativeRef.current) return;
|
|
48
111
|
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
49
|
-
console.log(
|
|
50
|
-
`[ControlledInputView] ${Platform.OS} blur command -> native`
|
|
51
|
-
);
|
|
52
112
|
Commands.blur(nativeRef.current);
|
|
53
113
|
}
|
|
54
114
|
},
|
|
55
115
|
focus: () => {
|
|
56
|
-
if (!nativeRef.current)
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
116
|
+
if (!nativeRef.current) return;
|
|
60
117
|
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
61
|
-
console.log(
|
|
62
|
-
`[ControlledInputView] ${Platform.OS} focus command -> native`
|
|
63
|
-
);
|
|
64
118
|
Commands.focus(nativeRef.current);
|
|
65
119
|
}
|
|
66
120
|
},
|
|
@@ -68,7 +122,12 @@ export const ControlledInputView = forwardRef<
|
|
|
68
122
|
|
|
69
123
|
return (
|
|
70
124
|
<ControlledInputViewNativeComponent
|
|
71
|
-
{...
|
|
125
|
+
{...rest}
|
|
126
|
+
style={viewStyle}
|
|
127
|
+
inputStyle={inputStyle as NativeProps['inputStyle']}
|
|
128
|
+
onTextChange={
|
|
129
|
+
onTextChange ? (e) => onTextChange(e.nativeEvent.value) : undefined
|
|
130
|
+
}
|
|
72
131
|
ref={nativeRef as any}
|
|
73
132
|
/>
|
|
74
133
|
);
|