react-native-keyboard-controller 1.12.7 → 1.13.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.
Files changed (148) hide show
  1. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardGestureAreaViewManager.kt +5 -0
  2. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ReactContext.kt +13 -0
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +0 -10
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/interactive/interpolators/Interpolator.kt +2 -1
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/interactive/interpolators/IosInterpolator.kt +2 -1
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/interactive/interpolators/LinearInterpolator.kt +1 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +13 -8
  8. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +71 -59
  9. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardGestureAreaViewManagerImpl.kt +4 -0
  10. package/android/src/main/java/com/reactnativekeyboardcontroller/modal/ModalAttachedWatcher.kt +80 -0
  11. package/android/src/main/java/com/reactnativekeyboardcontroller/modules/StatusBarManagerCompatModuleImpl.kt +6 -12
  12. package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +47 -13
  13. package/android/src/main/java/com/reactnativekeyboardcontroller/views/KeyboardGestureAreaReactViewGroup.kt +7 -0
  14. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardGestureAreaViewManager.kt +5 -0
  15. package/ios/extensions/UIView.swift +10 -0
  16. package/ios/observers/KeyboardMovementObserver.swift +7 -5
  17. package/ios/views/KeyboardControllerView.mm +30 -39
  18. package/lib/commonjs/animated.js +15 -30
  19. package/lib/commonjs/animated.js.map +1 -1
  20. package/lib/commonjs/bindings.js.map +1 -1
  21. package/lib/commonjs/bindings.native.js.map +1 -1
  22. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js +2 -14
  23. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js.map +1 -1
  24. package/lib/commonjs/components/KeyboardAvoidingView/index.js +4 -4
  25. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
  26. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +7 -6
  27. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
  28. package/lib/commonjs/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -1
  29. package/lib/commonjs/components/KeyboardAwareScrollView/utils.js.map +1 -1
  30. package/lib/commonjs/components/KeyboardStickyView/index.js +2 -2
  31. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
  32. package/lib/commonjs/components/KeyboardToolbar/Arrow.js +2 -2
  33. package/lib/commonjs/components/KeyboardToolbar/Arrow.js.map +1 -1
  34. package/lib/commonjs/components/KeyboardToolbar/Button.js +12 -12
  35. package/lib/commonjs/components/KeyboardToolbar/Button.js.map +1 -1
  36. package/lib/commonjs/components/KeyboardToolbar/index.js +33 -27
  37. package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
  38. package/lib/commonjs/components/index.js +2 -2
  39. package/lib/commonjs/components/index.js.map +1 -1
  40. package/lib/commonjs/context.js +3 -2
  41. package/lib/commonjs/context.js.map +1 -1
  42. package/lib/commonjs/event-handler.d.js +6 -0
  43. package/lib/commonjs/event-handler.d.js.map +1 -0
  44. package/lib/commonjs/event-handler.js +19 -0
  45. package/lib/commonjs/event-handler.js.map +1 -0
  46. package/lib/commonjs/event-handler.web.js +10 -0
  47. package/lib/commonjs/event-handler.web.js.map +1 -0
  48. package/lib/commonjs/event-mappings.js +9 -0
  49. package/lib/commonjs/event-mappings.js.map +1 -0
  50. package/lib/commonjs/hooks/index.js +8 -21
  51. package/lib/commonjs/hooks/index.js.map +1 -1
  52. package/lib/commonjs/hooks/useSyncEffect/index.js +37 -0
  53. package/lib/commonjs/hooks/useSyncEffect/index.js.map +1 -0
  54. package/lib/commonjs/internal.js +20 -44
  55. package/lib/commonjs/internal.js.map +1 -1
  56. package/lib/commonjs/monkey-patch.android.js +1 -1
  57. package/lib/commonjs/monkey-patch.android.js.map +1 -1
  58. package/lib/commonjs/monkey-patch.js.map +1 -1
  59. package/lib/commonjs/reanimated.js +1 -3
  60. package/lib/commonjs/reanimated.js.map +1 -1
  61. package/lib/commonjs/reanimated.native.js +1 -35
  62. package/lib/commonjs/reanimated.native.js.map +1 -1
  63. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js +1 -1
  64. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  65. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js +1 -1
  66. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
  67. package/lib/commonjs/types.js.map +1 -1
  68. package/lib/module/animated.js +16 -32
  69. package/lib/module/animated.js.map +1 -1
  70. package/lib/module/bindings.js.map +1 -1
  71. package/lib/module/bindings.native.js.map +1 -1
  72. package/lib/module/components/KeyboardAvoidingView/hooks.js +2 -14
  73. package/lib/module/components/KeyboardAvoidingView/hooks.js.map +1 -1
  74. package/lib/module/components/KeyboardAvoidingView/index.js +3 -3
  75. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
  76. package/lib/module/components/KeyboardAwareScrollView/index.js +6 -5
  77. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
  78. package/lib/module/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -1
  79. package/lib/module/components/KeyboardAwareScrollView/utils.js.map +1 -1
  80. package/lib/module/components/KeyboardStickyView/index.js +1 -1
  81. package/lib/module/components/KeyboardToolbar/Button.js +10 -10
  82. package/lib/module/components/KeyboardToolbar/Button.js.map +1 -1
  83. package/lib/module/components/KeyboardToolbar/index.js +31 -25
  84. package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
  85. package/lib/module/context.js +3 -2
  86. package/lib/module/context.js.map +1 -1
  87. package/lib/module/event-handler.d.js +2 -0
  88. package/lib/module/event-handler.d.js.map +1 -0
  89. package/lib/module/event-handler.js +14 -0
  90. package/lib/module/event-handler.js.map +1 -0
  91. package/lib/module/event-handler.web.js +5 -0
  92. package/lib/module/event-handler.web.js.map +1 -0
  93. package/lib/module/event-mappings.js +3 -0
  94. package/lib/module/event-mappings.js.map +1 -0
  95. package/lib/module/hooks/index.js +7 -21
  96. package/lib/module/hooks/index.js.map +1 -1
  97. package/lib/module/hooks/useSyncEffect/index.js +31 -0
  98. package/lib/module/hooks/useSyncEffect/index.js.map +1 -0
  99. package/lib/module/internal.js +21 -45
  100. package/lib/module/internal.js.map +1 -1
  101. package/lib/module/monkey-patch.js.map +1 -1
  102. package/lib/module/reanimated.js +0 -2
  103. package/lib/module/reanimated.js.map +1 -1
  104. package/lib/module/reanimated.native.js +0 -32
  105. package/lib/module/reanimated.native.js.map +1 -1
  106. package/lib/module/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
  107. package/lib/module/types.js.map +1 -1
  108. package/lib/typescript/components/KeyboardToolbar/Button.d.ts +2 -2
  109. package/lib/typescript/components/KeyboardToolbar/index.d.ts +4 -3
  110. package/lib/typescript/context.d.ts +3 -3
  111. package/lib/typescript/event-mappings.d.ts +2 -0
  112. package/lib/typescript/hooks/index.d.ts +1 -1
  113. package/lib/typescript/hooks/useSyncEffect/index.d.ts +14 -0
  114. package/lib/typescript/internal.d.ts +5 -19
  115. package/lib/typescript/reanimated.d.ts +1 -3
  116. package/lib/typescript/reanimated.native.d.ts +1 -3
  117. package/lib/typescript/specs/KeyboardGestureAreaNativeComponent.d.ts +2 -1
  118. package/lib/typescript/types.d.ts +6 -0
  119. package/package.json +11 -7
  120. package/src/animated.tsx +20 -43
  121. package/src/bindings.native.ts +1 -0
  122. package/src/bindings.ts +1 -0
  123. package/src/components/KeyboardAvoidingView/hooks.ts +2 -13
  124. package/src/components/KeyboardAvoidingView/index.tsx +1 -1
  125. package/src/components/KeyboardAwareScrollView/index.tsx +8 -3
  126. package/src/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.ts +1 -0
  127. package/src/components/KeyboardAwareScrollView/utils.ts +1 -0
  128. package/src/components/KeyboardToolbar/Button.tsx +11 -11
  129. package/src/components/KeyboardToolbar/index.tsx +45 -25
  130. package/src/context.ts +8 -6
  131. package/src/event-handler.d.ts +8 -0
  132. package/src/event-handler.js +15 -0
  133. package/src/event-handler.web.js +5 -0
  134. package/src/event-mappings.ts +14 -0
  135. package/src/hooks/index.ts +9 -16
  136. package/src/hooks/useSyncEffect/index.ts +36 -0
  137. package/src/internal.ts +34 -54
  138. package/src/monkey-patch.ts +1 -0
  139. package/src/reanimated.native.ts +0 -50
  140. package/src/reanimated.ts +1 -12
  141. package/src/specs/KeyboardGestureAreaNativeComponent.ts +5 -1
  142. package/src/types.ts +6 -0
  143. package/lib/commonjs/utils.js +0 -9
  144. package/lib/commonjs/utils.js.map +0 -1
  145. package/lib/module/utils.js +0 -2
  146. package/lib/module/utils.js.map +0 -1
  147. package/lib/typescript/utils.d.ts +0 -1
  148. package/src/utils.ts +0 -1
@@ -15,6 +15,7 @@ import { colors } from "./colors";
15
15
 
16
16
  import type { HEX, KeyboardToolbarTheme } from "./types";
17
17
  import type { ReactNode } from "react";
18
+ import type { GestureResponderEvent } from "react-native";
18
19
 
19
20
  export type KeyboardToolbarProps = {
20
21
  /** An element that is shown in the middle of the toolbar. */
@@ -35,15 +36,15 @@ export type KeyboardToolbarProps = {
35
36
  /**
36
37
  * A callback that is called when the user presses the next button along with the default action.
37
38
  */
38
- onNextCallback?: () => void;
39
+ onNextCallback?: (event: GestureResponderEvent) => void;
39
40
  /**
40
41
  * A callback that is called when the user presses the previous button along with the default action.
41
42
  */
42
- onPrevCallback?: () => void;
43
+ onPrevCallback?: (event: GestureResponderEvent) => void;
43
44
  /**
44
45
  * A callback that is called when the user presses the done button along with the default action.
45
46
  */
46
- onDoneCallback?: () => void;
47
+ onDoneCallback?: (event: GestureResponderEvent) => void;
47
48
  /**
48
49
  * A component that applies blur effect to the toolbar.
49
50
  */
@@ -53,6 +54,7 @@ export type KeyboardToolbarProps = {
53
54
  */
54
55
  opacity?: HEX;
55
56
  };
57
+
56
58
  const TEST_ID_KEYBOARD_TOOLBAR = "keyboard.toolbar";
57
59
  const TEST_ID_KEYBOARD_TOOLBAR_PREVIOUS = `${TEST_ID_KEYBOARD_TOOLBAR}.previous`;
58
60
  const TEST_ID_KEYBOARD_TOOLBAR_NEXT = `${TEST_ID_KEYBOARD_TOOLBAR}.next`;
@@ -115,18 +117,36 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
115
117
  const ButtonContainer = button || Button;
116
118
  const IconContainer = icon || Arrow;
117
119
 
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]);
120
+ const onPressNext = useCallback(
121
+ (event: GestureResponderEvent) => {
122
+ onNextCallback?.(event);
123
+
124
+ if (!event.isDefaultPrevented()) {
125
+ goToNextField();
126
+ }
127
+ },
128
+ [onNextCallback],
129
+ );
130
+ const onPressPrev = useCallback(
131
+ (event: GestureResponderEvent) => {
132
+ onPrevCallback?.(event);
133
+
134
+ if (!event.isDefaultPrevented()) {
135
+ goToPrevField();
136
+ }
137
+ },
138
+ [onPrevCallback],
139
+ );
140
+ const onPressDone = useCallback(
141
+ (event: GestureResponderEvent) => {
142
+ onDoneCallback?.(event);
143
+
144
+ if (!event.isDefaultPrevented()) {
145
+ dismissKeyboard();
146
+ }
147
+ },
148
+ [onDoneCallback],
149
+ );
130
150
 
131
151
  return (
132
152
  <KeyboardStickyView offset={offset}>
@@ -135,31 +155,31 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
135
155
  {showArrows && (
136
156
  <>
137
157
  <ButtonContainer
158
+ accessibilityHint="Moves focus to the previous field"
138
159
  accessibilityLabel="Previous"
139
- accessibilityHint="Will move focus to previous field"
140
160
  disabled={isPrevDisabled}
141
- onPress={onPressPrev}
142
161
  testID={TEST_ID_KEYBOARD_TOOLBAR_PREVIOUS}
143
162
  theme={theme}
163
+ onPress={onPressPrev}
144
164
  >
145
165
  <IconContainer
146
166
  disabled={isPrevDisabled}
147
- type="prev"
148
167
  theme={theme}
168
+ type="prev"
149
169
  />
150
170
  </ButtonContainer>
151
171
  <ButtonContainer
172
+ accessibilityHint="Moves focus to the next field"
152
173
  accessibilityLabel="Next"
153
- accessibilityHint="Will move focus to next field"
154
174
  disabled={isNextDisabled}
155
- onPress={onPressNext}
156
175
  testID={TEST_ID_KEYBOARD_TOOLBAR_NEXT}
157
176
  theme={theme}
177
+ onPress={onPressNext}
158
178
  >
159
179
  <IconContainer
160
180
  disabled={isNextDisabled}
161
- type="next"
162
181
  theme={theme}
182
+ type="next"
163
183
  />
164
184
  </ButtonContainer>
165
185
  </>
@@ -169,15 +189,15 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
169
189
  {content}
170
190
  </View>
171
191
  <ButtonContainer
192
+ accessibilityHint="Closes the keyboard"
172
193
  accessibilityLabel="Done"
173
- accessibilityHint="Will close the keyboard"
174
- onPress={onPressDone}
175
- testID={TEST_ID_KEYBOARD_TOOLBAR_DONE}
176
194
  rippleRadius={28}
177
195
  style={styles.doneButtonContainer}
196
+ testID={TEST_ID_KEYBOARD_TOOLBAR_DONE}
178
197
  theme={theme}
198
+ onPress={onPressDone}
179
199
  >
180
- <Text style={doneStyle} maxFontSizeMultiplier={1.3}>
200
+ <Text maxFontSizeMultiplier={1.3} style={doneStyle}>
181
201
  {doneText || "Done"}
182
202
  </Text>
183
203
  </ButtonContainer>
package/src/context.ts CHANGED
@@ -2,9 +2,9 @@ import { createContext, useContext } from "react";
2
2
  import { Animated } from "react-native";
3
3
 
4
4
  import type {
5
- FocusedInputHandlers,
5
+ FocusedInputHandler,
6
6
  FocusedInputLayoutChangedEvent,
7
- KeyboardHandlers,
7
+ KeyboardHandler,
8
8
  } from "./types";
9
9
  import type React from "react";
10
10
  import type { SharedValue } from "react-native-reanimated";
@@ -22,11 +22,12 @@ export type KeyboardAnimationContext = {
22
22
  animated: AnimatedContext;
23
23
  reanimated: ReanimatedContext;
24
24
  layout: SharedValue<FocusedInputLayoutChangedEvent | null>;
25
- setKeyboardHandlers: (handlers: KeyboardHandlers) => void;
26
- setInputHandlers: (handlers: FocusedInputHandlers) => void;
25
+ setKeyboardHandlers: (handlers: KeyboardHandler) => () => void;
26
+ setInputHandlers: (handlers: FocusedInputHandler) => () => void;
27
27
  setEnabled: React.Dispatch<React.SetStateAction<boolean>>;
28
28
  };
29
29
  const NOOP = () => {};
30
+ const NESTED_NOOP = () => NOOP;
30
31
  const withSharedValue = <T>(value: T): SharedValue<T> => ({
31
32
  value,
32
33
  addListener: NOOP,
@@ -48,10 +49,11 @@ const defaultContext: KeyboardAnimationContext = {
48
49
  height: DEFAULT_SHARED_VALUE,
49
50
  },
50
51
  layout: DEFAULT_LAYOUT,
51
- setKeyboardHandlers: NOOP,
52
- setInputHandlers: NOOP,
52
+ setKeyboardHandlers: NESTED_NOOP,
53
+ setInputHandlers: NESTED_NOOP,
53
54
  setEnabled: NOOP,
54
55
  };
56
+
55
57
  export const KeyboardContext = createContext(defaultContext);
56
58
  export const useKeyboardContext = () => {
57
59
  const context = useContext(KeyboardContext);
@@ -0,0 +1,8 @@
1
+ declare function registerEventHandler(
2
+ handler: (event: never) => void,
3
+ eventName: string,
4
+ viewTag: number,
5
+ ): number;
6
+ declare function unregisterEventHandler(id: number): void;
7
+
8
+ export { registerEventHandler, unregisterEventHandler };
@@ -0,0 +1,15 @@
1
+ let REACore = null;
2
+
3
+ try {
4
+ REACore = require("react-native-reanimated/src/core");
5
+ } catch (e1) {
6
+ try {
7
+ REACore = require("react-native-reanimated/src/reanimated2/core");
8
+ } catch (e2) {
9
+ console.warn("Failed to load REACore from both paths");
10
+ }
11
+ }
12
+ const registerEventHandler = REACore.registerEventHandler;
13
+ const unregisterEventHandler = REACore.unregisterEventHandler;
14
+
15
+ export { registerEventHandler, unregisterEventHandler };
@@ -0,0 +1,5 @@
1
+ const NOOP = () => {};
2
+ const registerEventHandler = NOOP;
3
+ const unregisterEventHandler = NOOP;
4
+
5
+ export { registerEventHandler, unregisterEventHandler };
@@ -0,0 +1,14 @@
1
+ import type { FocusedInputHandler, KeyboardHandler } from "./types";
2
+
3
+ export const keyboardEventsMap = new Map<keyof KeyboardHandler, string>([
4
+ ["onStart", "onKeyboardMoveStart"],
5
+ ["onMove", "onKeyboardMove"],
6
+ ["onEnd", "onKeyboardMoveEnd"],
7
+ ["onInteractive", "onKeyboardMoveInteractive"],
8
+ ]);
9
+ export const focusedInputEventsMap = new Map<keyof FocusedInputHandler, string>(
10
+ [
11
+ ["onChangeText", "onFocusedInputTextChanged"],
12
+ ["onSelectionChange", "onFocusedInputSelectionChanged"],
13
+ ],
14
+ );
@@ -3,7 +3,8 @@ import { useEffect } from "react";
3
3
  import { KeyboardController } from "../bindings";
4
4
  import { AndroidSoftInputModes } from "../constants";
5
5
  import { useKeyboardContext } from "../context";
6
- import { uuid } from "../utils";
6
+
7
+ import useSyncEffect from "./useSyncEffect";
7
8
 
8
9
  import type { AnimatedContext, ReanimatedContext } from "../context";
9
10
  import type { FocusedInputHandler, KeyboardHandler } from "../types";
@@ -39,14 +40,10 @@ export function useGenericKeyboardHandler(
39
40
  ) {
40
41
  const context = useKeyboardContext();
41
42
 
42
- useEffect(() => {
43
- const key = uuid();
44
-
45
- context.setKeyboardHandlers({ [key]: handler });
43
+ useSyncEffect(() => {
44
+ const cleanup = context.setKeyboardHandlers(handler);
46
45
 
47
- return () => {
48
- context.setKeyboardHandlers({ [key]: undefined });
49
- };
46
+ return () => cleanup();
50
47
  }, deps);
51
48
  }
52
49
 
@@ -71,19 +68,15 @@ export function useReanimatedFocusedInput() {
71
68
  }
72
69
 
73
70
  export function useFocusedInputHandler(
74
- handler?: FocusedInputHandler,
71
+ handler: FocusedInputHandler,
75
72
  deps?: DependencyList,
76
73
  ) {
77
74
  const context = useKeyboardContext();
78
75
 
79
- useEffect(() => {
80
- const key = uuid();
81
-
82
- context.setInputHandlers({ [key]: handler });
76
+ useSyncEffect(() => {
77
+ const cleanup = context.setInputHandlers(handler);
83
78
 
84
- return () => {
85
- context.setInputHandlers({ [key]: undefined });
86
- };
79
+ return () => cleanup();
87
80
  }, deps);
88
81
  }
89
82
 
@@ -0,0 +1,36 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ import type { DependencyList } from "react";
4
+
5
+ /**
6
+ * @description
7
+ * Equivalent to `useEffect` but will run the effect synchronously, i. e. before render.
8
+ *
9
+ * @param {effect} - imperative function
10
+ * @param {deps} - if present, effect will only activate if the values in the list change
11
+ *
12
+ * @author Kiryl Ziusko
13
+ * @since 1.13.0
14
+ * @version 1.0.0
15
+ */
16
+ const useSyncEffect: typeof useEffect = (effect, deps) => {
17
+ const cachedDeps = useRef<DependencyList | undefined | null>(null);
18
+ const areDepsEqual = deps?.every(
19
+ (el, index) => cachedDeps.current && el === cachedDeps.current[index],
20
+ );
21
+ const cleanupRef = useRef<(() => void) | void>();
22
+
23
+ if (!areDepsEqual || !cachedDeps.current) {
24
+ cleanupRef.current?.();
25
+ cleanupRef.current = effect();
26
+ cachedDeps.current = deps;
27
+ }
28
+
29
+ useEffect(() => {
30
+ return () => {
31
+ cleanupRef.current?.();
32
+ };
33
+ }, []);
34
+ };
35
+
36
+ export default useSyncEffect;
package/src/internal.ts CHANGED
@@ -1,64 +1,44 @@
1
- import { useCallback, useRef } from "react";
2
- import { Animated } from "react-native";
3
- import { useSharedValue } from "react-native-reanimated";
1
+ import { useRef } from "react";
2
+ import { Animated, findNodeHandle } from "react-native";
4
3
 
5
- import type { Handlers } from "./types";
4
+ import { registerEventHandler, unregisterEventHandler } from "./event-handler";
6
5
 
7
- type UntypedHandler = Record<string, (event: never) => void>;
8
- type SharedHandlersReturnType<T extends UntypedHandler> = [
9
- (handler: Handlers<T>) => void,
10
- <K extends keyof T>(type: K, event: Parameters<T[K]>[0]) => void,
11
- ];
6
+ type EventHandler = (event: never) => void;
7
+ type ComponentOrHandle = Parameters<typeof findNodeHandle>[0];
12
8
 
13
- /**
14
- * Hook for storing worklet handlers (objects with keys, where values are worklets).
15
- * Returns methods for setting handlers and broadcasting events in them.
16
- *
17
- * T is a generic that looks like:
18
- * @example
19
- * {
20
- * onEvent: () => {},
21
- * onEvent2: () => {},
22
- * }
23
- */
24
- export function useSharedHandlers<
25
- T extends UntypedHandler,
26
- >(): SharedHandlersReturnType<T> {
27
- const handlers = useSharedValue<Handlers<T>>({});
28
- const jsHandlers = useRef<Handlers<T>>({});
9
+ export function useEventHandlerRegistration<
10
+ H extends Partial<Record<string, EventHandler>>,
11
+ >(
12
+ map: Map<keyof H, string>,
13
+ viewTagRef: React.MutableRefObject<ComponentOrHandle>,
14
+ ) {
15
+ const onRegisterHandler = (handler: H) => {
16
+ const viewTag = findNodeHandle(viewTagRef.current);
17
+ const ids = Object.keys(handler).map((handlerName) => {
18
+ const eventName = map.get(handlerName as keyof H);
19
+ const functionToCall = handler[handlerName as keyof H];
29
20
 
30
- // since js -> worklet -> js call is asynchronous, we can not write handlers
31
- // straight into shared variable (using current shared value as a previous result),
32
- // since there may be a race condition in a call, and closure may have out-of-dated
33
- // values. As a result, some of handlers may be not written to "all handlers" object.
34
- // Below we are writing all handlers to `ref` and afterwards synchronize them with
35
- // shared value (since `refs` are not referring to actual value in worklets).
36
- // This approach allow us to update synchronously handlers in js thread (and it assures,
37
- // that it will have all of them) and then update them in worklet thread (calls are
38
- // happening in FIFO order, so we will always have actual value).
39
- const updateSharedHandlers = () => {
40
- // eslint-disable-next-line react-compiler/react-compiler
41
- handlers.value = jsHandlers.current;
42
- };
43
- const setHandlers = useCallback((handler: Handlers<T>) => {
44
- jsHandlers.current = {
45
- ...jsHandlers.current,
46
- ...handler,
47
- };
48
- updateSharedHandlers();
49
- }, []);
50
- const broadcast = <K extends keyof T>(
51
- type: K,
52
- event: Parameters<T[K]>[0],
53
- ) => {
54
- "worklet";
21
+ if (eventName && viewTag) {
22
+ return registerEventHandler(
23
+ (event: Parameters<NonNullable<H[keyof H]>>[0]) => {
24
+ "worklet";
25
+
26
+ functionToCall?.(event);
27
+ },
28
+ eventName,
29
+ viewTag,
30
+ );
31
+ }
55
32
 
56
- Object.keys(handlers.value).forEach((key) => {
57
- handlers.value[key]?.[type]?.(event);
33
+ return null;
58
34
  });
35
+
36
+ return () => {
37
+ ids.forEach((id) => (id ? unregisterEventHandler(id) : null));
38
+ };
59
39
  };
60
40
 
61
- return [setHandlers, broadcast];
41
+ return onRegisterHandler;
62
42
  }
63
43
 
64
44
  /**
@@ -76,7 +56,7 @@ export function useAnimatedValue(
76
56
  ): Animated.Value {
77
57
  const ref = useRef<Animated.Value | null>(null);
78
58
 
79
- if (ref.current == null) {
59
+ if (ref.current === null) {
80
60
  ref.current = new Animated.Value(initialValue, config);
81
61
  }
82
62
 
@@ -1,4 +1,5 @@
1
1
  // stub for all platforms
2
2
  const NOOP = () => {};
3
+
3
4
  export const applyMonkeyPatch = NOOP;
4
5
  export const revertMonkeyPatch = NOOP;
@@ -4,10 +4,6 @@ import type {
4
4
  EventWithName,
5
5
  FocusedInputLayoutChangedEvent,
6
6
  FocusedInputLayoutHandlerHook,
7
- FocusedInputSelectionChangedEvent,
8
- FocusedInputSelectionHandlerHook,
9
- FocusedInputTextChangedEvent,
10
- FocusedInputTextHandlerHook,
11
7
  KeyboardHandlerHook,
12
8
  NativeEvent,
13
9
  } from "./types";
@@ -84,49 +80,3 @@ export const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<
84
80
  doDependenciesDiffer,
85
81
  );
86
82
  };
87
-
88
- export const useFocusedInputTextHandler: FocusedInputTextHandlerHook<
89
- EventContext,
90
- EventWithName<FocusedInputTextChangedEvent>
91
- > = (handlers, dependencies) => {
92
- const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
93
-
94
- return useEvent(
95
- (event) => {
96
- "worklet";
97
- const { onFocusedInputTextChanged } = handlers;
98
-
99
- if (
100
- onFocusedInputTextChanged &&
101
- event.eventName.endsWith("onFocusedInputTextChanged")
102
- ) {
103
- onFocusedInputTextChanged(event, context);
104
- }
105
- },
106
- ["onFocusedInputTextChanged"],
107
- doDependenciesDiffer,
108
- );
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,15 +2,12 @@ import type {
2
2
  EventWithName,
3
3
  FocusedInputLayoutChangedEvent,
4
4
  FocusedInputLayoutHandlerHook,
5
- FocusedInputSelectionChangedEvent,
6
- FocusedInputSelectionHandlerHook,
7
- FocusedInputTextChangedEvent,
8
- FocusedInputTextHandlerHook,
9
5
  KeyboardHandlerHook,
10
6
  NativeEvent,
11
7
  } from "./types";
12
8
 
13
9
  const NOOP = () => () => {};
10
+
14
11
  export const useAnimatedKeyboardHandler: KeyboardHandlerHook<
15
12
  Record<string, unknown>,
16
13
  EventWithName<NativeEvent>
@@ -19,11 +16,3 @@ export const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<
19
16
  Record<string, unknown>,
20
17
  EventWithName<FocusedInputLayoutChangedEvent>
21
18
  > = NOOP;
22
- export const useFocusedInputTextHandler: FocusedInputTextHandlerHook<
23
- Record<string, unknown>,
24
- EventWithName<FocusedInputTextChangedEvent>
25
- > = NOOP;
26
- export const useFocusedInputSelectionHandler: FocusedInputSelectionHandlerHook<
27
- Record<string, unknown>,
28
- EventWithName<FocusedInputSelectionChangedEvent>
29
- > = NOOP;
@@ -2,12 +2,16 @@ import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNati
2
2
 
3
3
  import type { HostComponent } from "react-native";
4
4
  import type { ViewProps } from "react-native/Libraries/Components/View/ViewPropTypes";
5
- import type { WithDefault } from "react-native/Libraries/Types/CodegenTypes";
5
+ import type {
6
+ Double,
7
+ WithDefault,
8
+ } from "react-native/Libraries/Types/CodegenTypes";
6
9
 
7
10
  export interface NativeProps extends ViewProps {
8
11
  interpolator?: WithDefault<"linear" | "ios", "linear">;
9
12
  showOnSwipeUp?: boolean;
10
13
  enableSwipeToDismiss?: boolean;
14
+ offset?: Double;
11
15
  }
12
16
 
13
17
  export default codegenNativeComponent<NativeProps>("KeyboardGestureArea", {
package/src/types.ts CHANGED
@@ -47,6 +47,8 @@ export type EventWithName<T> = {
47
47
 
48
48
  // native View/Module declarations
49
49
  export type KeyboardControllerProps = {
50
+ //ref prop
51
+ ref?: React.Ref<React.Component<KeyboardControllerProps>>;
50
52
  // callback props
51
53
  onKeyboardMoveStart?: (
52
54
  e: NativeSyntheticEvent<EventWithName<NativeEvent>>,
@@ -101,6 +103,10 @@ export type KeyboardGestureAreaProps = {
101
103
  * Defaults to `true`.
102
104
  */
103
105
  enableSwipeToDismiss?: boolean;
106
+ /**
107
+ * Extra distance to the keyboard.
108
+ */
109
+ offset?: number;
104
110
  } & ViewProps;
105
111
 
106
112
  export type Direction = "next" | "prev" | "current";
@@ -1,9 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.uuid = void 0;
7
- const uuid = () => Math.random().toString(36).slice(-6);
8
- exports.uuid = uuid;
9
- //# sourceMappingURL=utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["uuid","Math","random","toString","slice","exports"],"sources":["utils.ts"],"sourcesContent":["export const uuid = () => Math.random().toString(36).slice(-6);\n"],"mappings":";;;;;;AAAO,MAAMA,IAAI,GAAGA,CAAA,KAAMC,IAAI,CAACC,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC,CAACC,KAAK,CAAC,CAAC,CAAC,CAAC;AAACC,OAAA,CAAAL,IAAA,GAAAA,IAAA","ignoreList":[]}
@@ -1,2 +0,0 @@
1
- export const uuid = () => Math.random().toString(36).slice(-6);
2
- //# sourceMappingURL=utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["uuid","Math","random","toString","slice"],"sources":["utils.ts"],"sourcesContent":["export const uuid = () => Math.random().toString(36).slice(-6);\n"],"mappings":"AAAA,OAAO,MAAMA,IAAI,GAAGA,CAAA,KAAMC,IAAI,CAACC,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC,CAACC,KAAK,CAAC,CAAC,CAAC,CAAC","ignoreList":[]}
@@ -1 +0,0 @@
1
- export declare const uuid: () => string;
package/src/utils.ts DELETED
@@ -1 +0,0 @@
1
- export const uuid = () => Math.random().toString(36).slice(-6);