react-native-keyboard-controller 1.11.6 → 1.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/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputLayoutChangedEvent.kt +1 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputSelectionChangedEvent.kt +51 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputTextChangedEvent.kt +1 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/EditText.kt +79 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +1 -2
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/View.kt +1 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/interactive/interpolators/IosInterpolator.kt +1 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +32 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +1 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +2 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/ui/FrameScheduler.kt +40 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +1 -1
- package/ios/KeyboardController-Bridging-Header.h +1 -0
- package/ios/core/KeyboardAnimation.swift +77 -0
- package/ios/core/SpringAnimation.swift +60 -0
- package/ios/core/UIUtils.swift +11 -0
- package/ios/delegates/KCTextInputCompositeDelegate.swift +148 -0
- package/ios/events/FocusedInputSelectionChangedEvent.h +15 -0
- package/ios/events/FocusedInputSelectionChangedEvent.m +76 -0
- package/ios/objc/RCTUITextView+DelegateManager.h +14 -0
- package/ios/objc/RCTUITextView+DelegateManager.m +26 -0
- package/ios/observers/FocusedInputObserver.swift +74 -13
- package/ios/observers/KeyboardMovementObserver.swift +39 -2
- package/ios/views/KeyboardControllerView.mm +45 -8
- package/ios/views/KeyboardControllerViewManager.mm +1 -0
- package/ios/views/KeyboardControllerViewManager.swift +10 -2
- package/lib/commonjs/animated.js +8 -0
- package/lib/commonjs/animated.js.map +1 -1
- package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js +5 -5
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardToolbar/index.js +25 -7
- package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardToolbar/types.js.map +1 -1
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/reanimated.js +2 -1
- package/lib/commonjs/reanimated.js.map +1 -1
- package/lib/commonjs/reanimated.native.js +18 -1
- package/lib/commonjs/reanimated.native.js.map +1 -1
- package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/animated.js +9 -1
- package/lib/module/animated.js.map +1 -1
- package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/module/components/KeyboardAwareScrollView/index.js +5 -5
- package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
- package/lib/module/components/KeyboardToolbar/index.js +26 -8
- package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/module/components/KeyboardToolbar/types.js.map +1 -1
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/reanimated.js +1 -0
- package/lib/module/reanimated.js.map +1 -1
- package/lib/module/reanimated.native.js +16 -0
- package/lib/module/reanimated.native.js.map +1 -1
- package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +20 -0
- package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +8 -0
- package/lib/typescript/components/KeyboardStickyView/index.d.ts +15 -0
- package/lib/typescript/components/KeyboardToolbar/index.d.ts +21 -1
- package/lib/typescript/components/KeyboardToolbar/types.d.ts +3 -1
- package/lib/typescript/components/index.d.ts +3 -0
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/reanimated.d.ts +2 -1
- package/lib/typescript/reanimated.native.d.ts +7 -4
- package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +16 -0
- package/lib/typescript/types.d.ts +21 -0
- package/package.json +4 -3
- package/src/animated.tsx +12 -0
- package/src/components/KeyboardAvoidingView/index.tsx +5 -2
- package/src/components/KeyboardAwareScrollView/index.tsx +81 -81
- package/src/components/KeyboardStickyView/index.tsx +1 -1
- package/src/components/KeyboardToolbar/index.tsx +47 -7
- package/src/components/KeyboardToolbar/types.ts +25 -1
- package/src/components/index.ts +3 -0
- package/src/index.ts +6 -1
- package/src/reanimated.native.ts +30 -3
- package/src/reanimated.ts +6 -0
- package/src/specs/KeyboardControllerViewNativeComponent.ts +17 -0
- package/src/types.ts +31 -0
- package/ios/KeyboardController.xcodeproj/project.pbxproj +0 -387
- package/ios/observers/TextChangeObserver.swift +0 -41
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { View, ViewProps } from "react-native";
|
|
3
|
+
export type KeyboardStickyViewProps = {
|
|
4
|
+
/**
|
|
5
|
+
* Specify additional offset to the view for given keyboard state.
|
|
6
|
+
*/
|
|
7
|
+
offset?: {
|
|
8
|
+
/**
|
|
9
|
+
* Adds additional `translateY` when keyboard is close. By default `0`.
|
|
10
|
+
*/
|
|
11
|
+
closed?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Adds additional `translateY` when keyboard is open. By default `0`.
|
|
14
|
+
*/
|
|
15
|
+
opened?: number;
|
|
16
|
+
};
|
|
17
|
+
} & ViewProps;
|
|
3
18
|
declare const KeyboardStickyView: React.ForwardRefExoticComponent<{
|
|
4
19
|
/**
|
|
5
20
|
* Specify additional offset to the view for given keyboard state.
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import Arrow from "./Arrow";
|
|
3
3
|
import Button from "./Button";
|
|
4
4
|
import { colors } from "./colors";
|
|
5
|
-
import type { KeyboardToolbarTheme } from "./types";
|
|
5
|
+
import type { HEX, KeyboardToolbarTheme } from "./types";
|
|
6
6
|
import type { ReactNode } from "react";
|
|
7
7
|
export type KeyboardToolbarProps = {
|
|
8
8
|
/** An element that is shown in the middle of the toolbar. */
|
|
@@ -20,6 +20,26 @@ export type KeyboardToolbarProps = {
|
|
|
20
20
|
* and want to show only `Done` button. Default to `true`.
|
|
21
21
|
*/
|
|
22
22
|
showArrows?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* A callback that is called when the user presses the next button along with the default action.
|
|
25
|
+
*/
|
|
26
|
+
onNextCallback?: () => void;
|
|
27
|
+
/**
|
|
28
|
+
* A callback that is called when the user presses the previous button along with the default action.
|
|
29
|
+
*/
|
|
30
|
+
onPrevCallback?: () => void;
|
|
31
|
+
/**
|
|
32
|
+
* A callback that is called when the user presses the done button along with the default action.
|
|
33
|
+
*/
|
|
34
|
+
onDoneCallback?: () => void;
|
|
35
|
+
/**
|
|
36
|
+
* A component that applies blur effect to the toolbar.
|
|
37
|
+
*/
|
|
38
|
+
blur?: JSX.Element | null;
|
|
39
|
+
/**
|
|
40
|
+
* A value for container opacity in hexadecimal format (e.g. `ff`). Default value is `ff`.
|
|
41
|
+
*/
|
|
42
|
+
opacity?: HEX;
|
|
23
43
|
};
|
|
24
44
|
/**
|
|
25
45
|
* `KeyboardToolbar` is a component that is shown above the keyboard with `Prev`/`Next` and
|
|
@@ -5,7 +5,7 @@ type Theme = {
|
|
|
5
5
|
/** Color for arrow when it's disabled */
|
|
6
6
|
disabled: ColorValue;
|
|
7
7
|
/** Keyboard toolbar background color */
|
|
8
|
-
background:
|
|
8
|
+
background: string;
|
|
9
9
|
/** Color for ripple effect (on button touch) on Android */
|
|
10
10
|
ripple: ColorValue;
|
|
11
11
|
};
|
|
@@ -13,4 +13,6 @@ export type KeyboardToolbarTheme = {
|
|
|
13
13
|
light: Theme;
|
|
14
14
|
dark: Theme;
|
|
15
15
|
};
|
|
16
|
+
type HexSymbol = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f";
|
|
17
|
+
export type HEX = `${HexSymbol}${HexSymbol}`;
|
|
16
18
|
export {};
|
|
@@ -2,4 +2,7 @@ export { default as KeyboardAvoidingView } from "./KeyboardAvoidingView";
|
|
|
2
2
|
export { default as KeyboardStickyView } from "./KeyboardStickyView";
|
|
3
3
|
export { default as KeyboardAwareScrollView } from "./KeyboardAwareScrollView";
|
|
4
4
|
export { default as KeyboardToolbar, DefaultKeyboardToolbarTheme, } from "./KeyboardToolbar";
|
|
5
|
+
export type { KeyboardAvoidingViewProps } from "./KeyboardAvoidingView";
|
|
6
|
+
export type { KeyboardStickyViewProps } from "./KeyboardStickyView";
|
|
7
|
+
export type { KeyboardAwareScrollViewProps } from "./KeyboardAwareScrollView";
|
|
5
8
|
export type { KeyboardToolbarProps } from "./KeyboardToolbar";
|
|
@@ -5,4 +5,4 @@ export * from "./hooks";
|
|
|
5
5
|
export * from "./constants";
|
|
6
6
|
export * from "./types";
|
|
7
7
|
export { KeyboardAvoidingView, KeyboardStickyView, KeyboardAwareScrollView, KeyboardToolbar, DefaultKeyboardToolbarTheme, } from "./components";
|
|
8
|
-
export type { KeyboardToolbarProps } from "./components";
|
|
8
|
+
export type { KeyboardAvoidingViewProps, KeyboardStickyViewProps, KeyboardAwareScrollViewProps, KeyboardToolbarProps, } from "./components";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { EventWithName, FocusedInputLayoutChangedEvent, FocusedInputLayoutHandlerHook, FocusedInputTextChangedEvent, FocusedInputTextHandlerHook, KeyboardHandlerHook, NativeEvent } from "./types";
|
|
1
|
+
import type { EventWithName, FocusedInputLayoutChangedEvent, FocusedInputLayoutHandlerHook, FocusedInputSelectionChangedEvent, FocusedInputSelectionHandlerHook, FocusedInputTextChangedEvent, FocusedInputTextHandlerHook, KeyboardHandlerHook, NativeEvent } from "./types";
|
|
2
2
|
export declare const useAnimatedKeyboardHandler: KeyboardHandlerHook<Record<string, unknown>, EventWithName<NativeEvent>>;
|
|
3
3
|
export declare const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<Record<string, unknown>, EventWithName<FocusedInputLayoutChangedEvent>>;
|
|
4
4
|
export declare const useFocusedInputTextHandler: FocusedInputTextHandlerHook<Record<string, unknown>, EventWithName<FocusedInputTextChangedEvent>>;
|
|
5
|
+
export declare const useFocusedInputSelectionHandler: FocusedInputSelectionHandlerHook<Record<string, unknown>, EventWithName<FocusedInputSelectionChangedEvent>>;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type { EventWithName, FocusedInputLayoutChangedEvent, FocusedInputLayoutHandlerHook, FocusedInputTextChangedEvent, FocusedInputTextHandlerHook, KeyboardHandlerHook, NativeEvent } from "./types";
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
1
|
+
import type { EventWithName, FocusedInputLayoutChangedEvent, FocusedInputLayoutHandlerHook, FocusedInputSelectionChangedEvent, FocusedInputSelectionHandlerHook, FocusedInputTextChangedEvent, FocusedInputTextHandlerHook, KeyboardHandlerHook, NativeEvent } from "./types";
|
|
2
|
+
type EventContext = Record<string, unknown>;
|
|
3
|
+
export declare const useAnimatedKeyboardHandler: KeyboardHandlerHook<EventContext, EventWithName<NativeEvent>>;
|
|
4
|
+
export declare const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<EventContext, EventWithName<FocusedInputLayoutChangedEvent>>;
|
|
5
|
+
export declare const useFocusedInputTextHandler: FocusedInputTextHandlerHook<EventContext, EventWithName<FocusedInputTextChangedEvent>>;
|
|
6
|
+
export declare const useFocusedInputSelectionHandler: FocusedInputSelectionHandlerHook<EventContext, EventWithName<FocusedInputSelectionChangedEvent>>;
|
|
7
|
+
export {};
|
|
@@ -22,6 +22,21 @@ type FocusedInputLayoutChangedEvent = Readonly<{
|
|
|
22
22
|
type FocusedInputTextChangedEvent = Readonly<{
|
|
23
23
|
text: string;
|
|
24
24
|
}>;
|
|
25
|
+
type FocusedInputSelectionChangedEvent = Readonly<{
|
|
26
|
+
target: Int32;
|
|
27
|
+
selection: {
|
|
28
|
+
start: {
|
|
29
|
+
x: Double;
|
|
30
|
+
y: Double;
|
|
31
|
+
position: Int32;
|
|
32
|
+
};
|
|
33
|
+
end: {
|
|
34
|
+
x: Double;
|
|
35
|
+
y: Double;
|
|
36
|
+
position: Int32;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}>;
|
|
25
40
|
export interface NativeProps extends ViewProps {
|
|
26
41
|
enabled?: boolean;
|
|
27
42
|
statusBarTranslucent?: boolean;
|
|
@@ -32,6 +47,7 @@ export interface NativeProps extends ViewProps {
|
|
|
32
47
|
onKeyboardMoveInteractive?: DirectEventHandler<KeyboardMoveEvent>;
|
|
33
48
|
onFocusedInputLayoutChanged?: DirectEventHandler<FocusedInputLayoutChangedEvent>;
|
|
34
49
|
onFocusedInputTextChanged?: DirectEventHandler<FocusedInputTextChangedEvent>;
|
|
50
|
+
onFocusedInputSelectionChanged?: DirectEventHandler<FocusedInputSelectionChangedEvent>;
|
|
35
51
|
}
|
|
36
52
|
declare const _default: HostComponent<NativeProps>;
|
|
37
53
|
export default _default;
|
|
@@ -20,6 +20,21 @@ export type FocusedInputLayoutChangedEvent = {
|
|
|
20
20
|
export type FocusedInputTextChangedEvent = {
|
|
21
21
|
text: string;
|
|
22
22
|
};
|
|
23
|
+
export type FocusedInputSelectionChangedEvent = {
|
|
24
|
+
target: number;
|
|
25
|
+
selection: {
|
|
26
|
+
start: {
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
position: number;
|
|
30
|
+
};
|
|
31
|
+
end: {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
position: number;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
};
|
|
23
38
|
export type EventWithName<T> = {
|
|
24
39
|
eventName: string;
|
|
25
40
|
} & T;
|
|
@@ -30,9 +45,11 @@ export type KeyboardControllerProps = {
|
|
|
30
45
|
onKeyboardMoveInteractive?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
31
46
|
onFocusedInputLayoutChanged?: (e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>) => void;
|
|
32
47
|
onFocusedInputTextChanged?: (e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>) => void;
|
|
48
|
+
onFocusedInputSelectionChanged?: (e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>) => void;
|
|
33
49
|
onKeyboardMoveReanimated?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
34
50
|
onFocusedInputLayoutChangedReanimated?: (e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>) => void;
|
|
35
51
|
onFocusedInputTextChangedReanimated?: (e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>) => void;
|
|
52
|
+
onFocusedInputSelectionChangedReanimated?: (e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>) => void;
|
|
36
53
|
statusBarTranslucent?: boolean;
|
|
37
54
|
navigationBarTranslucent?: boolean;
|
|
38
55
|
enabled?: boolean;
|
|
@@ -90,6 +107,9 @@ export type FocusedInputLayoutHandlerHook<TContext, Event> = (handlers: {
|
|
|
90
107
|
export type FocusedInputTextHandlerHook<TContext, Event> = (handlers: {
|
|
91
108
|
onFocusedInputTextChanged?: (e: FocusedInputTextChangedEvent, context: TContext) => void;
|
|
92
109
|
}, dependencies?: unknown[]) => (e: NativeSyntheticEvent<Event>) => void;
|
|
110
|
+
export type FocusedInputSelectionHandlerHook<TContext, Event> = (handlers: {
|
|
111
|
+
onFocusedInputSelectionChanged?: (e: FocusedInputSelectionChangedEvent, context: TContext) => void;
|
|
112
|
+
}, dependencies?: unknown[]) => (e: NativeSyntheticEvent<Event>) => void;
|
|
93
113
|
export type Handlers<T> = Record<string, T | undefined>;
|
|
94
114
|
export type KeyboardHandler = Partial<{
|
|
95
115
|
onStart: (e: NativeEvent) => void;
|
|
@@ -100,5 +120,6 @@ export type KeyboardHandler = Partial<{
|
|
|
100
120
|
export type KeyboardHandlers = Handlers<KeyboardHandler>;
|
|
101
121
|
export type FocusedInputHandler = Partial<{
|
|
102
122
|
onChangeText: (e: FocusedInputTextChangedEvent) => void;
|
|
123
|
+
onSelectionChange: (e: FocusedInputSelectionChangedEvent) => void;
|
|
103
124
|
}>;
|
|
104
125
|
export type FocusedInputHandlers = Handlers<FocusedInputHandler>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-keyboard-controller",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Keyboard manager which works in identical way on both iOS and Android",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"focused input",
|
|
48
48
|
"text changed",
|
|
49
49
|
"avoiding view",
|
|
50
|
+
"avoid keyboard",
|
|
50
51
|
"sticky view",
|
|
51
52
|
"keyboard aware scroll view",
|
|
52
53
|
"keyboard toolbar",
|
|
@@ -87,9 +88,9 @@
|
|
|
87
88
|
"pod-install": "^0.1.0",
|
|
88
89
|
"prettier": "^2.8.8",
|
|
89
90
|
"react": "18.2.0",
|
|
90
|
-
"react-native": "0.
|
|
91
|
+
"react-native": "0.74.0",
|
|
91
92
|
"react-native-builder-bob": "^0.18.0",
|
|
92
|
-
"react-native-reanimated": "3.
|
|
93
|
+
"react-native-reanimated": "3.9.0",
|
|
93
94
|
"release-it": "^14.2.2",
|
|
94
95
|
"typescript": "5.0.4"
|
|
95
96
|
},
|
package/src/animated.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import { applyMonkeyPatch, revertMonkeyPatch } from "./monkey-patch";
|
|
|
9
9
|
import {
|
|
10
10
|
useAnimatedKeyboardHandler,
|
|
11
11
|
useFocusedInputLayoutHandler,
|
|
12
|
+
useFocusedInputSelectionHandler,
|
|
12
13
|
useFocusedInputTextHandler,
|
|
13
14
|
} from "./reanimated";
|
|
14
15
|
|
|
@@ -191,6 +192,16 @@ export const KeyboardProvider = ({
|
|
|
191
192
|
},
|
|
192
193
|
[],
|
|
193
194
|
);
|
|
195
|
+
const inputSelectionHandler = useFocusedInputSelectionHandler(
|
|
196
|
+
{
|
|
197
|
+
onFocusedInputSelectionChanged: (e) => {
|
|
198
|
+
"worklet";
|
|
199
|
+
|
|
200
|
+
broadcastInputEvents("onSelectionChange", e);
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
[],
|
|
204
|
+
);
|
|
194
205
|
// effects
|
|
195
206
|
useEffect(() => {
|
|
196
207
|
if (enabled) {
|
|
@@ -210,6 +221,7 @@ export const KeyboardProvider = ({
|
|
|
210
221
|
onKeyboardMoveInteractive={onKeyboardMove}
|
|
211
222
|
onFocusedInputLayoutChangedReanimated={inputLayoutHandler}
|
|
212
223
|
onFocusedInputTextChangedReanimated={inputTextHandler}
|
|
224
|
+
onFocusedInputSelectionChangedReanimated={inputSelectionHandler}
|
|
213
225
|
navigationBarTranslucent={navigationBarTranslucent}
|
|
214
226
|
statusBarTranslucent={statusBarTranslucent}
|
|
215
227
|
style={styles.container}
|
|
@@ -12,7 +12,7 @@ import { useKeyboardAnimation } from "./hooks";
|
|
|
12
12
|
|
|
13
13
|
import type { LayoutRectangle, ViewProps } from "react-native";
|
|
14
14
|
|
|
15
|
-
type
|
|
15
|
+
export type KeyboardAvoidingViewProps = {
|
|
16
16
|
/**
|
|
17
17
|
* Specify how to react to the presence of the keyboard.
|
|
18
18
|
*/
|
|
@@ -47,7 +47,10 @@ const defaultLayout: LayoutRectangle = {
|
|
|
47
47
|
* View that moves out of the way when the keyboard appears by automatically
|
|
48
48
|
* adjusting its height, position, or bottom padding.
|
|
49
49
|
*/
|
|
50
|
-
const KeyboardAvoidingView = forwardRef<
|
|
50
|
+
const KeyboardAvoidingView = forwardRef<
|
|
51
|
+
View,
|
|
52
|
+
React.PropsWithChildren<KeyboardAvoidingViewProps>
|
|
53
|
+
>(
|
|
51
54
|
(
|
|
52
55
|
{
|
|
53
56
|
behavior,
|
|
@@ -24,7 +24,7 @@ import type {
|
|
|
24
24
|
} from "react-native";
|
|
25
25
|
import type { FocusedInputLayoutChangedEvent } from "react-native-keyboard-controller";
|
|
26
26
|
|
|
27
|
-
type KeyboardAwareScrollViewProps = {
|
|
27
|
+
export type KeyboardAwareScrollViewProps = {
|
|
28
28
|
/** The distance between keyboard and focused `TextInput` when keyboard is shown. Default is `0`. */
|
|
29
29
|
bottomOffset?: number;
|
|
30
30
|
/** Prevents automatic scrolling of the `ScrollView` when the keyboard gets hidden, maintaining the current screen position. Default is `false`. */
|
|
@@ -212,77 +212,74 @@ const KeyboardAwareScrollView = forwardRef<
|
|
|
212
212
|
);
|
|
213
213
|
|
|
214
214
|
useSmoothKeyboardHandler(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
// this value to achieve smooth hide effect
|
|
258
|
-
scrollBeforeKeyboardMovement.value = position.value;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (focusWasChanged && !keyboardWillAppear.value) {
|
|
262
|
-
// update position on scroll value, so `onEnd` handler
|
|
263
|
-
// will pick up correct values
|
|
264
|
-
position.value += maybeScroll(e.height, true);
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
onMove: (e) => {
|
|
268
|
-
"worklet";
|
|
269
|
-
|
|
270
|
-
currentKeyboardFrameHeight.value = e.height;
|
|
271
|
-
|
|
272
|
-
// if the user has set disableScrollOnKeyboardHide, only auto-scroll when the keyboard opens
|
|
273
|
-
if (!disableScrollOnKeyboardHide || keyboardWillAppear.value) {
|
|
274
|
-
maybeScroll(e.height);
|
|
275
|
-
}
|
|
276
|
-
},
|
|
277
|
-
onEnd: (e) => {
|
|
278
|
-
"worklet";
|
|
279
|
-
|
|
280
|
-
keyboardHeight.value = e.height;
|
|
281
|
-
scrollPosition.value = position.value;
|
|
282
|
-
},
|
|
215
|
+
{
|
|
216
|
+
onStart: (e) => {
|
|
217
|
+
"worklet";
|
|
218
|
+
|
|
219
|
+
const keyboardWillChangeSize =
|
|
220
|
+
keyboardHeight.value !== e.height && e.height > 0;
|
|
221
|
+
keyboardWillAppear.value = e.height > 0 && keyboardHeight.value === 0;
|
|
222
|
+
const keyboardWillHide = e.height === 0;
|
|
223
|
+
const focusWasChanged =
|
|
224
|
+
(tag.value !== e.target && e.target !== -1) ||
|
|
225
|
+
keyboardWillChangeSize;
|
|
226
|
+
|
|
227
|
+
if (keyboardWillChangeSize) {
|
|
228
|
+
initialKeyboardSize.value = keyboardHeight.value;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (keyboardWillHide) {
|
|
232
|
+
// on back transition need to interpolate as [0, keyboardHeight]
|
|
233
|
+
initialKeyboardSize.value = 0;
|
|
234
|
+
scrollPosition.value = scrollBeforeKeyboardMovement.value;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (
|
|
238
|
+
keyboardWillAppear.value ||
|
|
239
|
+
keyboardWillChangeSize ||
|
|
240
|
+
focusWasChanged
|
|
241
|
+
) {
|
|
242
|
+
// persist scroll value
|
|
243
|
+
scrollPosition.value = position.value;
|
|
244
|
+
// just persist height - later will be used in interpolation
|
|
245
|
+
keyboardHeight.value = e.height;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// focus was changed
|
|
249
|
+
if (focusWasChanged) {
|
|
250
|
+
tag.value = e.target;
|
|
251
|
+
|
|
252
|
+
// save position of focused text input when keyboard starts to move
|
|
253
|
+
layout.value = input.value;
|
|
254
|
+
// save current scroll position - when keyboard will hide we'll reuse
|
|
255
|
+
// this value to achieve smooth hide effect
|
|
256
|
+
scrollBeforeKeyboardMovement.value = position.value;
|
|
283
257
|
}
|
|
284
|
-
|
|
285
|
-
|
|
258
|
+
|
|
259
|
+
if (focusWasChanged && !keyboardWillAppear.value) {
|
|
260
|
+
// update position on scroll value, so `onEnd` handler
|
|
261
|
+
// will pick up correct values
|
|
262
|
+
position.value += maybeScroll(e.height, true);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
onMove: (e) => {
|
|
266
|
+
"worklet";
|
|
267
|
+
|
|
268
|
+
currentKeyboardFrameHeight.value = e.height;
|
|
269
|
+
|
|
270
|
+
// if the user has set disableScrollOnKeyboardHide, only auto-scroll when the keyboard opens
|
|
271
|
+
if (!disableScrollOnKeyboardHide || keyboardWillAppear.value) {
|
|
272
|
+
maybeScroll(e.height);
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
onEnd: (e) => {
|
|
276
|
+
"worklet";
|
|
277
|
+
|
|
278
|
+
keyboardHeight.value = e.height;
|
|
279
|
+
scrollPosition.value = position.value;
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
[height, maybeScroll, disableScrollOnKeyboardHide],
|
|
286
283
|
);
|
|
287
284
|
|
|
288
285
|
useAnimatedReaction(
|
|
@@ -303,16 +300,19 @@ const KeyboardAwareScrollView = forwardRef<
|
|
|
303
300
|
);
|
|
304
301
|
|
|
305
302
|
const view = useAnimatedStyle(
|
|
306
|
-
() =>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
303
|
+
() =>
|
|
304
|
+
enabled
|
|
305
|
+
? {
|
|
306
|
+
// animations become choppy when scrolling to the end of the `ScrollView` (when the last input is focused)
|
|
307
|
+
// this happens because the layout recalculates on every frame. To avoid this we slightly increase padding
|
|
308
|
+
// by `+1`. In this way we assure, that `scrollTo` will never scroll to the end, because it uses interpolation
|
|
309
|
+
// from 0 to `keyboardHeight`, and here our padding is `keyboardHeight + 1`. It allows us not to re-run layout
|
|
310
|
+
// re-calculation on every animation frame and it helps to achieve smooth animation.
|
|
311
|
+
// see: https://github.com/kirillzyusko/react-native-keyboard-controller/pull/342
|
|
312
|
+
paddingBottom: currentKeyboardFrameHeight.value + 1,
|
|
313
|
+
}
|
|
314
|
+
: {},
|
|
315
|
+
[enabled],
|
|
316
316
|
);
|
|
317
317
|
|
|
318
318
|
return (
|
|
@@ -8,7 +8,7 @@ import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller
|
|
|
8
8
|
|
|
9
9
|
import type { View, ViewProps } from "react-native";
|
|
10
10
|
|
|
11
|
-
type KeyboardStickyViewProps = {
|
|
11
|
+
export type KeyboardStickyViewProps = {
|
|
12
12
|
/**
|
|
13
13
|
* Specify additional offset to the view for given keyboard state.
|
|
14
14
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useMemo, useState } from "react";
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { StyleSheet, Text, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -13,7 +13,7 @@ import Arrow from "./Arrow";
|
|
|
13
13
|
import Button from "./Button";
|
|
14
14
|
import { colors } from "./colors";
|
|
15
15
|
|
|
16
|
-
import type { KeyboardToolbarTheme } from "./types";
|
|
16
|
+
import type { HEX, KeyboardToolbarTheme } from "./types";
|
|
17
17
|
import type { ReactNode } from "react";
|
|
18
18
|
|
|
19
19
|
export type KeyboardToolbarProps = {
|
|
@@ -32,6 +32,26 @@ export type KeyboardToolbarProps = {
|
|
|
32
32
|
* and want to show only `Done` button. Default to `true`.
|
|
33
33
|
*/
|
|
34
34
|
showArrows?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* A callback that is called when the user presses the next button along with the default action.
|
|
37
|
+
*/
|
|
38
|
+
onNextCallback?: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* A callback that is called when the user presses the previous button along with the default action.
|
|
41
|
+
*/
|
|
42
|
+
onPrevCallback?: () => void;
|
|
43
|
+
/**
|
|
44
|
+
* A callback that is called when the user presses the done button along with the default action.
|
|
45
|
+
*/
|
|
46
|
+
onDoneCallback?: () => void;
|
|
47
|
+
/**
|
|
48
|
+
* A component that applies blur effect to the toolbar.
|
|
49
|
+
*/
|
|
50
|
+
blur?: JSX.Element | null;
|
|
51
|
+
/**
|
|
52
|
+
* A value for container opacity in hexadecimal format (e.g. `ff`). Default value is `ff`.
|
|
53
|
+
*/
|
|
54
|
+
opacity?: HEX;
|
|
35
55
|
};
|
|
36
56
|
const TEST_ID_KEYBOARD_TOOLBAR = "keyboard.toolbar";
|
|
37
57
|
const TEST_ID_KEYBOARD_TOOLBAR_PREVIOUS = `${TEST_ID_KEYBOARD_TOOLBAR}.previous`;
|
|
@@ -40,6 +60,7 @@ const TEST_ID_KEYBOARD_TOOLBAR_CONTENT = `${TEST_ID_KEYBOARD_TOOLBAR}.content`;
|
|
|
40
60
|
const TEST_ID_KEYBOARD_TOOLBAR_DONE = `${TEST_ID_KEYBOARD_TOOLBAR}.done`;
|
|
41
61
|
|
|
42
62
|
const KEYBOARD_TOOLBAR_HEIGHT = 42;
|
|
63
|
+
const DEFAULT_OPACITY: HEX = "FF";
|
|
43
64
|
const offset = { closed: KEYBOARD_TOOLBAR_HEIGHT };
|
|
44
65
|
|
|
45
66
|
const dismissKeyboard = () => KeyboardController.dismiss();
|
|
@@ -57,6 +78,11 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
|
|
|
57
78
|
button,
|
|
58
79
|
icon,
|
|
59
80
|
showArrows = true,
|
|
81
|
+
onNextCallback,
|
|
82
|
+
onPrevCallback,
|
|
83
|
+
onDoneCallback,
|
|
84
|
+
blur = null,
|
|
85
|
+
opacity = DEFAULT_OPACITY,
|
|
60
86
|
}) => {
|
|
61
87
|
const colorScheme = useColorScheme();
|
|
62
88
|
const [inputs, setInputs] = useState({
|
|
@@ -81,24 +107,38 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
|
|
|
81
107
|
() => [
|
|
82
108
|
styles.toolbar,
|
|
83
109
|
{
|
|
84
|
-
backgroundColor: theme[colorScheme].background
|
|
110
|
+
backgroundColor: `${theme[colorScheme].background}${opacity}`,
|
|
85
111
|
},
|
|
86
112
|
],
|
|
87
|
-
[colorScheme, theme],
|
|
113
|
+
[colorScheme, opacity, theme],
|
|
88
114
|
);
|
|
89
115
|
const ButtonContainer = button || Button;
|
|
90
116
|
const IconContainer = icon || Arrow;
|
|
91
117
|
|
|
118
|
+
const onPressNext = useCallback(() => {
|
|
119
|
+
goToNextField();
|
|
120
|
+
onNextCallback?.();
|
|
121
|
+
}, [onNextCallback]);
|
|
122
|
+
const onPressPrev = useCallback(() => {
|
|
123
|
+
goToPrevField();
|
|
124
|
+
onPrevCallback?.();
|
|
125
|
+
}, [onPrevCallback]);
|
|
126
|
+
const onPressDone = useCallback(() => {
|
|
127
|
+
dismissKeyboard();
|
|
128
|
+
onDoneCallback?.();
|
|
129
|
+
}, [onDoneCallback]);
|
|
130
|
+
|
|
92
131
|
return (
|
|
93
132
|
<KeyboardStickyView offset={offset}>
|
|
94
133
|
<View style={toolbarStyle} testID={TEST_ID_KEYBOARD_TOOLBAR}>
|
|
134
|
+
{blur}
|
|
95
135
|
{showArrows && (
|
|
96
136
|
<>
|
|
97
137
|
<ButtonContainer
|
|
98
138
|
accessibilityLabel="Previous"
|
|
99
139
|
accessibilityHint="Will move focus to previous field"
|
|
100
140
|
disabled={isPrevDisabled}
|
|
101
|
-
onPress={
|
|
141
|
+
onPress={onPressPrev}
|
|
102
142
|
testID={TEST_ID_KEYBOARD_TOOLBAR_PREVIOUS}
|
|
103
143
|
theme={theme}
|
|
104
144
|
>
|
|
@@ -112,7 +152,7 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
|
|
|
112
152
|
accessibilityLabel="Next"
|
|
113
153
|
accessibilityHint="Will move focus to next field"
|
|
114
154
|
disabled={isNextDisabled}
|
|
115
|
-
onPress={
|
|
155
|
+
onPress={onPressNext}
|
|
116
156
|
testID={TEST_ID_KEYBOARD_TOOLBAR_NEXT}
|
|
117
157
|
theme={theme}
|
|
118
158
|
>
|
|
@@ -131,7 +171,7 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
|
|
|
131
171
|
<ButtonContainer
|
|
132
172
|
accessibilityLabel="Done"
|
|
133
173
|
accessibilityHint="Will close the keyboard"
|
|
134
|
-
onPress={
|
|
174
|
+
onPress={onPressDone}
|
|
135
175
|
testID={TEST_ID_KEYBOARD_TOOLBAR_DONE}
|
|
136
176
|
rippleRadius={28}
|
|
137
177
|
style={styles.doneButtonContainer}
|
|
@@ -6,7 +6,7 @@ type Theme = {
|
|
|
6
6
|
/** Color for arrow when it's disabled */
|
|
7
7
|
disabled: ColorValue;
|
|
8
8
|
/** Keyboard toolbar background color */
|
|
9
|
-
background:
|
|
9
|
+
background: string;
|
|
10
10
|
/** Color for ripple effect (on button touch) on Android */
|
|
11
11
|
ripple: ColorValue;
|
|
12
12
|
};
|
|
@@ -14,3 +14,27 @@ export type KeyboardToolbarTheme = {
|
|
|
14
14
|
light: Theme;
|
|
15
15
|
dark: Theme;
|
|
16
16
|
};
|
|
17
|
+
type HexSymbol =
|
|
18
|
+
| "0"
|
|
19
|
+
| "1"
|
|
20
|
+
| "2"
|
|
21
|
+
| "3"
|
|
22
|
+
| "4"
|
|
23
|
+
| "5"
|
|
24
|
+
| "6"
|
|
25
|
+
| "7"
|
|
26
|
+
| "8"
|
|
27
|
+
| "9"
|
|
28
|
+
| "A"
|
|
29
|
+
| "B"
|
|
30
|
+
| "C"
|
|
31
|
+
| "D"
|
|
32
|
+
| "E"
|
|
33
|
+
| "F"
|
|
34
|
+
| "a"
|
|
35
|
+
| "b"
|
|
36
|
+
| "c"
|
|
37
|
+
| "d"
|
|
38
|
+
| "e"
|
|
39
|
+
| "f";
|
|
40
|
+
export type HEX = `${HexSymbol}${HexSymbol}`;
|
package/src/components/index.ts
CHANGED
|
@@ -5,4 +5,7 @@ export {
|
|
|
5
5
|
default as KeyboardToolbar,
|
|
6
6
|
DefaultKeyboardToolbarTheme,
|
|
7
7
|
} from "./KeyboardToolbar";
|
|
8
|
+
export type { KeyboardAvoidingViewProps } from "./KeyboardAvoidingView";
|
|
9
|
+
export type { KeyboardStickyViewProps } from "./KeyboardStickyView";
|
|
10
|
+
export type { KeyboardAwareScrollViewProps } from "./KeyboardAwareScrollView";
|
|
8
11
|
export type { KeyboardToolbarProps } from "./KeyboardToolbar";
|
package/src/index.ts
CHANGED
|
@@ -13,4 +13,9 @@ export {
|
|
|
13
13
|
KeyboardToolbar,
|
|
14
14
|
DefaultKeyboardToolbarTheme,
|
|
15
15
|
} from "./components";
|
|
16
|
-
export type {
|
|
16
|
+
export type {
|
|
17
|
+
KeyboardAvoidingViewProps,
|
|
18
|
+
KeyboardStickyViewProps,
|
|
19
|
+
KeyboardAwareScrollViewProps,
|
|
20
|
+
KeyboardToolbarProps,
|
|
21
|
+
} from "./components";
|