react-native-controlled-input 0.11.0 → 0.12.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/android/build.gradle +1 -0
- package/android/src/main/java/com/controlledinput/ControlledInputView.kt +22 -1
- package/lib/module/index.js +42 -10
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +63 -10
- package/src/react-native-codegen.d.ts +16 -0
package/android/build.gradle
CHANGED
|
@@ -88,5 +88,6 @@ dependencies {
|
|
|
88
88
|
implementation 'androidx.compose.ui:ui-tooling-preview'
|
|
89
89
|
implementation 'androidx.compose.material3:material3'
|
|
90
90
|
implementation 'androidx.activity:activity-compose:1.12.2'
|
|
91
|
+
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.7'
|
|
91
92
|
debugImplementation 'androidx.compose.ui:ui-tooling'
|
|
92
93
|
}
|
|
@@ -11,11 +11,16 @@ import androidx.compose.runtime.remember
|
|
|
11
11
|
import androidx.compose.ui.focus.FocusRequester
|
|
12
12
|
import androidx.compose.ui.platform.ComposeView
|
|
13
13
|
import androidx.compose.ui.platform.LocalFocusManager
|
|
14
|
+
import androidx.compose.ui.platform.ViewCompositionStrategy
|
|
15
|
+
import androidx.lifecycle.Lifecycle
|
|
16
|
+
import androidx.lifecycle.LifecycleOwner
|
|
17
|
+
import androidx.lifecycle.LifecycleRegistry
|
|
18
|
+
import androidx.lifecycle.setViewTreeLifecycleOwner
|
|
14
19
|
import com.facebook.react.bridge.ReactContext
|
|
15
20
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
16
21
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
17
22
|
|
|
18
|
-
class ControlledInputView : LinearLayout {
|
|
23
|
+
class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
19
24
|
constructor(context: Context) : super(context) {
|
|
20
25
|
configureComponent(context)
|
|
21
26
|
}
|
|
@@ -32,10 +37,24 @@ class ControlledInputView : LinearLayout {
|
|
|
32
37
|
configureComponent(context)
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
private val lifecycleRegistry = LifecycleRegistry(this)
|
|
41
|
+
override val lifecycle: Lifecycle get() = lifecycleRegistry
|
|
42
|
+
|
|
35
43
|
internal lateinit var viewModel: JetpackComposeViewModel
|
|
36
44
|
private val blurSignal = MutableStateFlow(0)
|
|
37
45
|
private val focusSignal = MutableStateFlow(0)
|
|
38
46
|
|
|
47
|
+
override fun onAttachedToWindow() {
|
|
48
|
+
super.onAttachedToWindow()
|
|
49
|
+
setViewTreeLifecycleOwner(this)
|
|
50
|
+
lifecycleRegistry.currentState = Lifecycle.State.RESUMED
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
override fun onDetachedFromWindow() {
|
|
54
|
+
super.onDetachedFromWindow()
|
|
55
|
+
lifecycleRegistry.currentState = Lifecycle.State.CREATED
|
|
56
|
+
}
|
|
57
|
+
|
|
39
58
|
fun blur() {
|
|
40
59
|
// триггерим compose снять фокус
|
|
41
60
|
blurSignal.value = blurSignal.value + 1
|
|
@@ -68,6 +87,8 @@ class ControlledInputView : LinearLayout {
|
|
|
68
87
|
)
|
|
69
88
|
it.setBackgroundColor(android.graphics.Color.TRANSPARENT)
|
|
70
89
|
|
|
90
|
+
it.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
|
91
|
+
|
|
71
92
|
viewModel = JetpackComposeViewModel()
|
|
72
93
|
|
|
73
94
|
it.setContent {
|
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,11 +21,30 @@ function resolveAndroidComposeViewPadding(flat) {
|
|
|
18
21
|
export const ControlledInputView = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(({
|
|
19
22
|
style,
|
|
20
23
|
onTextChange,
|
|
24
|
+
onFocus,
|
|
25
|
+
onBlur,
|
|
21
26
|
selectionColor,
|
|
22
27
|
placeholderTextColor,
|
|
23
28
|
...rest
|
|
24
29
|
}, ref) => {
|
|
25
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]);
|
|
26
48
|
const flattenedStyle = StyleSheet.flatten(style) ?? {};
|
|
27
49
|
let viewStyle;
|
|
28
50
|
let inputStyle;
|
|
@@ -59,18 +81,26 @@ export const ControlledInputView = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(({
|
|
|
59
81
|
onTextChange(e.nativeEvent.value);
|
|
60
82
|
}
|
|
61
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
|
+
};
|
|
62
96
|
useImperativeHandle(ref, () => ({
|
|
63
97
|
blur: () => {
|
|
64
|
-
if (!nativeRef.current) return;
|
|
65
|
-
|
|
66
|
-
Commands.blur(nativeRef.current);
|
|
67
|
-
}
|
|
98
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
99
|
+
TextInputState.blurTextInput(nativeRef.current);
|
|
68
100
|
},
|
|
69
101
|
focus: () => {
|
|
70
|
-
if (!nativeRef.current) return;
|
|
71
|
-
|
|
72
|
-
Commands.focus(nativeRef.current);
|
|
73
|
-
}
|
|
102
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
103
|
+
TextInputState.focusTextInput(nativeRef.current);
|
|
74
104
|
}
|
|
75
105
|
}));
|
|
76
106
|
return /*#__PURE__*/_jsx(ControlledInputViewNativeComponent, {
|
|
@@ -80,6 +110,8 @@ export const ControlledInputView = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(({
|
|
|
80
110
|
style: viewStyle,
|
|
81
111
|
inputStyle: inputStyle,
|
|
82
112
|
onTextChange: handleTextChange,
|
|
113
|
+
onFocus: handleFocus,
|
|
114
|
+
onBlur: handleBlur,
|
|
83
115
|
ref: nativeRef
|
|
84
116
|
});
|
|
85
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":[]}
|
|
@@ -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
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';
|
|
@@ -43,6 +46,13 @@ export type ControlledInputViewProps = Omit<
|
|
|
43
46
|
onTextChange?: (value: string) => void;
|
|
44
47
|
};
|
|
45
48
|
|
|
49
|
+
type ControlledInputFocusEvent = Parameters<
|
|
50
|
+
NonNullable<NativeProps['onFocus']>
|
|
51
|
+
>[0];
|
|
52
|
+
type ControlledInputBlurEvent = Parameters<
|
|
53
|
+
NonNullable<NativeProps['onBlur']>
|
|
54
|
+
>[0];
|
|
55
|
+
|
|
46
56
|
// All style props that Android handles via Compose instead of the native View layer
|
|
47
57
|
const androidComposeHandledKeys = [
|
|
48
58
|
'color',
|
|
@@ -75,12 +85,43 @@ function resolveAndroidComposeViewPadding(flat: Record<string, any>) {
|
|
|
75
85
|
export const ControlledInputView = memo(
|
|
76
86
|
forwardRef<ControlledInputViewRef, ControlledInputViewProps>(
|
|
77
87
|
(
|
|
78
|
-
{
|
|
88
|
+
{
|
|
89
|
+
style,
|
|
90
|
+
onTextChange,
|
|
91
|
+
onFocus,
|
|
92
|
+
onBlur,
|
|
93
|
+
selectionColor,
|
|
94
|
+
placeholderTextColor,
|
|
95
|
+
...rest
|
|
96
|
+
},
|
|
79
97
|
ref
|
|
80
98
|
) => {
|
|
81
99
|
const nativeRef =
|
|
82
100
|
useRef<ElementRef<typeof ControlledInputViewNativeComponent>>(null);
|
|
83
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
|
+
|
|
84
125
|
const flattenedStyle = (StyleSheet.flatten(style) ?? {}) as TextStyle;
|
|
85
126
|
|
|
86
127
|
let viewStyle: ViewStyle;
|
|
@@ -132,18 +173,28 @@ export const ControlledInputView = memo(
|
|
|
132
173
|
}
|
|
133
174
|
};
|
|
134
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
|
+
|
|
135
190
|
useImperativeHandle(ref, () => ({
|
|
136
191
|
blur: () => {
|
|
137
|
-
if (!nativeRef.current) return;
|
|
138
|
-
|
|
139
|
-
Commands.blur(nativeRef.current);
|
|
140
|
-
}
|
|
192
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
193
|
+
TextInputState.blurTextInput(nativeRef.current);
|
|
141
194
|
},
|
|
142
195
|
focus: () => {
|
|
143
|
-
if (!nativeRef.current) return;
|
|
144
|
-
|
|
145
|
-
Commands.focus(nativeRef.current);
|
|
146
|
-
}
|
|
196
|
+
if (!nativeRef.current || !isNativePlatform) return;
|
|
197
|
+
TextInputState.focusTextInput(nativeRef.current);
|
|
147
198
|
},
|
|
148
199
|
}));
|
|
149
200
|
|
|
@@ -155,6 +206,8 @@ export const ControlledInputView = memo(
|
|
|
155
206
|
style={viewStyle}
|
|
156
207
|
inputStyle={inputStyle}
|
|
157
208
|
onTextChange={handleTextChange}
|
|
209
|
+
onFocus={handleFocus}
|
|
210
|
+
onBlur={handleBlur}
|
|
158
211
|
ref={nativeRef}
|
|
159
212
|
/>
|
|
160
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
|
+
}
|