react-native-keyboard-controller 1.11.7 → 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.
Files changed (83) hide show
  1. package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputSelectionChangedEvent.kt +51 -0
  2. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/EditText.kt +79 -0
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +1 -2
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/View.kt +1 -1
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/interactive/interpolators/IosInterpolator.kt +1 -1
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +32 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +1 -1
  8. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +2 -0
  9. package/android/src/main/java/com/reactnativekeyboardcontroller/ui/FrameScheduler.kt +40 -0
  10. package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +1 -1
  11. package/ios/KeyboardController-Bridging-Header.h +1 -0
  12. package/ios/core/KeyboardAnimation.swift +77 -0
  13. package/ios/core/SpringAnimation.swift +60 -0
  14. package/ios/core/UIUtils.swift +11 -0
  15. package/ios/delegates/KCTextInputCompositeDelegate.swift +148 -0
  16. package/ios/events/FocusedInputSelectionChangedEvent.h +15 -0
  17. package/ios/events/FocusedInputSelectionChangedEvent.m +76 -0
  18. package/ios/objc/RCTUITextView+DelegateManager.h +14 -0
  19. package/ios/objc/RCTUITextView+DelegateManager.m +26 -0
  20. package/ios/observers/FocusedInputObserver.swift +74 -13
  21. package/ios/observers/KeyboardMovementObserver.swift +39 -2
  22. package/ios/views/KeyboardControllerView.mm +45 -8
  23. package/ios/views/KeyboardControllerViewManager.mm +1 -0
  24. package/ios/views/KeyboardControllerViewManager.swift +10 -2
  25. package/lib/commonjs/animated.js +8 -0
  26. package/lib/commonjs/animated.js.map +1 -1
  27. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
  28. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +1 -1
  29. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
  30. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
  31. package/lib/commonjs/components/KeyboardToolbar/index.js +25 -7
  32. package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
  33. package/lib/commonjs/components/KeyboardToolbar/types.js.map +1 -1
  34. package/lib/commonjs/components/index.js.map +1 -1
  35. package/lib/commonjs/index.js.map +1 -1
  36. package/lib/commonjs/reanimated.js +2 -1
  37. package/lib/commonjs/reanimated.js.map +1 -1
  38. package/lib/commonjs/reanimated.native.js +18 -1
  39. package/lib/commonjs/reanimated.native.js.map +1 -1
  40. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  41. package/lib/commonjs/types.js.map +1 -1
  42. package/lib/module/animated.js +9 -1
  43. package/lib/module/animated.js.map +1 -1
  44. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
  45. package/lib/module/components/KeyboardAwareScrollView/index.js +1 -1
  46. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
  47. package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
  48. package/lib/module/components/KeyboardToolbar/index.js +26 -8
  49. package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
  50. package/lib/module/components/KeyboardToolbar/types.js.map +1 -1
  51. package/lib/module/components/index.js.map +1 -1
  52. package/lib/module/index.js.map +1 -1
  53. package/lib/module/reanimated.js +1 -0
  54. package/lib/module/reanimated.js.map +1 -1
  55. package/lib/module/reanimated.native.js +16 -0
  56. package/lib/module/reanimated.native.js.map +1 -1
  57. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  58. package/lib/module/types.js.map +1 -1
  59. package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +20 -0
  60. package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +8 -0
  61. package/lib/typescript/components/KeyboardStickyView/index.d.ts +15 -0
  62. package/lib/typescript/components/KeyboardToolbar/index.d.ts +21 -1
  63. package/lib/typescript/components/KeyboardToolbar/types.d.ts +3 -1
  64. package/lib/typescript/components/index.d.ts +3 -0
  65. package/lib/typescript/index.d.ts +1 -1
  66. package/lib/typescript/reanimated.d.ts +2 -1
  67. package/lib/typescript/reanimated.native.d.ts +7 -4
  68. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +16 -0
  69. package/lib/typescript/types.d.ts +21 -0
  70. package/package.json +4 -3
  71. package/src/animated.tsx +12 -0
  72. package/src/components/KeyboardAvoidingView/index.tsx +5 -2
  73. package/src/components/KeyboardAwareScrollView/index.tsx +2 -2
  74. package/src/components/KeyboardStickyView/index.tsx +1 -1
  75. package/src/components/KeyboardToolbar/index.tsx +47 -7
  76. package/src/components/KeyboardToolbar/types.ts +25 -1
  77. package/src/components/index.ts +3 -0
  78. package/src/index.ts +6 -1
  79. package/src/reanimated.native.ts +30 -3
  80. package/src/reanimated.ts +6 -0
  81. package/src/specs/KeyboardControllerViewNativeComponent.ts +17 -0
  82. package/src/types.ts +31 -0
  83. package/ios/observers/TextChangeObserver.swift +0 -41
@@ -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: ColorValue;
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
- export declare const useAnimatedKeyboardHandler: KeyboardHandlerHook<Record<string, unknown>, EventWithName<NativeEvent>>;
3
- export declare const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<Record<string, unknown>, EventWithName<FocusedInputLayoutChangedEvent>>;
4
- export declare const useFocusedInputTextHandler: FocusedInputTextHandlerHook<Record<string, unknown>, EventWithName<FocusedInputTextChangedEvent>>;
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.11.7",
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.73.6",
91
+ "react-native": "0.74.0",
91
92
  "react-native-builder-bob": "^0.18.0",
92
- "react-native-reanimated": "3.8.0",
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 Props = {
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<View, React.PropsWithChildren<Props>>(
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`. */
@@ -303,7 +303,7 @@ const KeyboardAwareScrollView = forwardRef<
303
303
  () =>
304
304
  enabled
305
305
  ? {
306
- // animations become laggy when scrolling to the end of the `ScrollView` (when the last input is focused)
306
+ // animations become choppy when scrolling to the end of the `ScrollView` (when the last input is focused)
307
307
  // this happens because the layout recalculates on every frame. To avoid this we slightly increase padding
308
308
  // by `+1`. In this way we assure, that `scrollTo` will never scroll to the end, because it uses interpolation
309
309
  // from 0 to `keyboardHeight`, and here our padding is `keyboardHeight + 1`. It allows us not to re-run layout
@@ -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={goToPrevField}
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={goToNextField}
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={dismissKeyboard}
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: ColorValue;
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}`;
@@ -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 { KeyboardToolbarProps } from "./components";
16
+ export type {
17
+ KeyboardAvoidingViewProps,
18
+ KeyboardStickyViewProps,
19
+ KeyboardAwareScrollViewProps,
20
+ KeyboardToolbarProps,
21
+ } from "./components";
@@ -4,14 +4,18 @@ import type {
4
4
  EventWithName,
5
5
  FocusedInputLayoutChangedEvent,
6
6
  FocusedInputLayoutHandlerHook,
7
+ FocusedInputSelectionChangedEvent,
8
+ FocusedInputSelectionHandlerHook,
7
9
  FocusedInputTextChangedEvent,
8
10
  FocusedInputTextHandlerHook,
9
11
  KeyboardHandlerHook,
10
12
  NativeEvent,
11
13
  } from "./types";
12
14
 
15
+ type EventContext = Record<string, unknown>;
16
+
13
17
  export const useAnimatedKeyboardHandler: KeyboardHandlerHook<
14
- Record<string, unknown>,
18
+ EventContext,
15
19
  EventWithName<NativeEvent>
16
20
  > = (handlers, dependencies) => {
17
21
  const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
@@ -59,7 +63,7 @@ export const useAnimatedKeyboardHandler: KeyboardHandlerHook<
59
63
  };
60
64
 
61
65
  export const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<
62
- Record<string, unknown>,
66
+ EventContext,
63
67
  EventWithName<FocusedInputLayoutChangedEvent>
64
68
  > = (handlers, dependencies) => {
65
69
  const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
@@ -82,7 +86,7 @@ export const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<
82
86
  };
83
87
 
84
88
  export const useFocusedInputTextHandler: FocusedInputTextHandlerHook<
85
- Record<string, unknown>,
89
+ EventContext,
86
90
  EventWithName<FocusedInputTextChangedEvent>
87
91
  > = (handlers, dependencies) => {
88
92
  const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
@@ -103,3 +107,26 @@ export const useFocusedInputTextHandler: FocusedInputTextHandlerHook<
103
107
  doDependenciesDiffer,
104
108
  );
105
109
  };
110
+
111
+ export const useFocusedInputSelectionHandler: FocusedInputSelectionHandlerHook<
112
+ EventContext,
113
+ EventWithName<FocusedInputSelectionChangedEvent>
114
+ > = (handlers, dependencies) => {
115
+ const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
116
+
117
+ return useEvent(
118
+ (event) => {
119
+ "worklet";
120
+ const { onFocusedInputSelectionChanged } = handlers;
121
+
122
+ if (
123
+ onFocusedInputSelectionChanged &&
124
+ event.eventName.endsWith("onFocusedInputSelectionChanged")
125
+ ) {
126
+ onFocusedInputSelectionChanged(event, context);
127
+ }
128
+ },
129
+ ["onFocusedInputSelectionChanged"],
130
+ doDependenciesDiffer,
131
+ );
132
+ };
package/src/reanimated.ts CHANGED
@@ -2,6 +2,8 @@ import type {
2
2
  EventWithName,
3
3
  FocusedInputLayoutChangedEvent,
4
4
  FocusedInputLayoutHandlerHook,
5
+ FocusedInputSelectionChangedEvent,
6
+ FocusedInputSelectionHandlerHook,
5
7
  FocusedInputTextChangedEvent,
6
8
  FocusedInputTextHandlerHook,
7
9
  KeyboardHandlerHook,
@@ -21,3 +23,7 @@ export const useFocusedInputTextHandler: FocusedInputTextHandlerHook<
21
23
  Record<string, unknown>,
22
24
  EventWithName<FocusedInputTextChangedEvent>
23
25
  > = NOOP;
26
+ export const useFocusedInputSelectionHandler: FocusedInputSelectionHandlerHook<
27
+ Record<string, unknown>,
28
+ EventWithName<FocusedInputSelectionChangedEvent>
29
+ > = NOOP;
@@ -32,6 +32,22 @@ type FocusedInputTextChangedEvent = Readonly<{
32
32
  text: string;
33
33
  }>;
34
34
 
35
+ type FocusedInputSelectionChangedEvent = Readonly<{
36
+ target: Int32;
37
+ selection: {
38
+ start: {
39
+ x: Double;
40
+ y: Double;
41
+ position: Int32;
42
+ };
43
+ end: {
44
+ x: Double;
45
+ y: Double;
46
+ position: Int32;
47
+ };
48
+ };
49
+ }>;
50
+
35
51
  export interface NativeProps extends ViewProps {
36
52
  // props
37
53
  enabled?: boolean;
@@ -46,6 +62,7 @@ export interface NativeProps extends ViewProps {
46
62
  /// focused input
47
63
  onFocusedInputLayoutChanged?: DirectEventHandler<FocusedInputLayoutChangedEvent>;
48
64
  onFocusedInputTextChanged?: DirectEventHandler<FocusedInputTextChangedEvent>;
65
+ onFocusedInputSelectionChanged?: DirectEventHandler<FocusedInputSelectionChangedEvent>;
49
66
  }
50
67
 
51
68
  export default codegenNativeComponent<NativeProps>(
package/src/types.ts CHANGED
@@ -26,6 +26,21 @@ export type FocusedInputLayoutChangedEvent = {
26
26
  export type FocusedInputTextChangedEvent = {
27
27
  text: string;
28
28
  };
29
+ export type FocusedInputSelectionChangedEvent = {
30
+ target: number;
31
+ selection: {
32
+ start: {
33
+ x: number;
34
+ y: number;
35
+ position: number;
36
+ };
37
+ end: {
38
+ x: number;
39
+ y: number;
40
+ position: number;
41
+ };
42
+ };
43
+ };
29
44
  export type EventWithName<T> = {
30
45
  eventName: string;
31
46
  } & T;
@@ -51,6 +66,9 @@ export type KeyboardControllerProps = {
51
66
  onFocusedInputTextChanged?: (
52
67
  e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>,
53
68
  ) => void;
69
+ onFocusedInputSelectionChanged?: (
70
+ e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>,
71
+ ) => void;
54
72
  // fake props used to activate reanimated bindings
55
73
  onKeyboardMoveReanimated?: (
56
74
  e: NativeSyntheticEvent<EventWithName<NativeEvent>>,
@@ -61,6 +79,9 @@ export type KeyboardControllerProps = {
61
79
  onFocusedInputTextChangedReanimated?: (
62
80
  e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>,
63
81
  ) => void;
82
+ onFocusedInputSelectionChangedReanimated?: (
83
+ e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>,
84
+ ) => void;
64
85
  // props
65
86
  statusBarTranslucent?: boolean;
66
87
  navigationBarTranslucent?: boolean;
@@ -153,6 +174,15 @@ export type FocusedInputTextHandlerHook<TContext, Event> = (
153
174
  },
154
175
  dependencies?: unknown[],
155
176
  ) => (e: NativeSyntheticEvent<Event>) => void;
177
+ export type FocusedInputSelectionHandlerHook<TContext, Event> = (
178
+ handlers: {
179
+ onFocusedInputSelectionChanged?: (
180
+ e: FocusedInputSelectionChangedEvent,
181
+ context: TContext,
182
+ ) => void;
183
+ },
184
+ dependencies?: unknown[],
185
+ ) => (e: NativeSyntheticEvent<Event>) => void;
156
186
 
157
187
  // package types
158
188
  export type Handlers<T> = Record<string, T | undefined>;
@@ -165,5 +195,6 @@ export type KeyboardHandler = Partial<{
165
195
  export type KeyboardHandlers = Handlers<KeyboardHandler>;
166
196
  export type FocusedInputHandler = Partial<{
167
197
  onChangeText: (e: FocusedInputTextChangedEvent) => void;
198
+ onSelectionChange: (e: FocusedInputSelectionChangedEvent) => void;
168
199
  }>;
169
200
  export type FocusedInputHandlers = Handlers<FocusedInputHandler>;