@react-native-ohos/react-native-keyboard-controller 1.16.6-rc.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 (269) hide show
  1. package/LICENSE +21 -0
  2. package/README.OpenSource +11 -0
  3. package/README.md +19 -0
  4. package/harmony/keyboard_controller/BuildProfile.ets +17 -0
  5. package/harmony/keyboard_controller/Index.ets +7 -0
  6. package/harmony/keyboard_controller/ResourceTable.txt +1 -0
  7. package/harmony/keyboard_controller/build-profile.json5 +31 -0
  8. package/harmony/keyboard_controller/consumer-rules.txt +0 -0
  9. package/harmony/keyboard_controller/hvigorfile.ts +6 -0
  10. package/harmony/keyboard_controller/obfuscation-rules.txt +18 -0
  11. package/harmony/keyboard_controller/oh-package.json5 +11 -0
  12. package/harmony/keyboard_controller/src/main/cpp/CMakeLists.txt +7 -0
  13. package/harmony/keyboard_controller/src/main/cpp/EventEmitters.cpp +96 -0
  14. package/harmony/keyboard_controller/src/main/cpp/EventEmitters.h +90 -0
  15. package/harmony/keyboard_controller/src/main/cpp/KeyboardControllerViewComponentDescriptor.h +73 -0
  16. package/harmony/keyboard_controller/src/main/cpp/KeyboardControllerViewComponentInstance.cpp +172 -0
  17. package/harmony/keyboard_controller/src/main/cpp/KeyboardControllerViewComponentInstance.h +76 -0
  18. package/harmony/keyboard_controller/src/main/cpp/KeyboardControllerViewJSIBinder.h +44 -0
  19. package/harmony/keyboard_controller/src/main/cpp/KeyboardGestureAreaComponentDescriptor.h +58 -0
  20. package/harmony/keyboard_controller/src/main/cpp/KeyboardGestureAreaComponentInstance.cpp +87 -0
  21. package/harmony/keyboard_controller/src/main/cpp/KeyboardGestureAreaComponentInstance.h +62 -0
  22. package/harmony/keyboard_controller/src/main/cpp/KeyboardGestureAreaJSIBinder.h +39 -0
  23. package/harmony/keyboard_controller/src/main/cpp/RNKeyboardController.cpp +25 -0
  24. package/harmony/keyboard_controller/src/main/cpp/RNKeyboardController.h +27 -0
  25. package/harmony/keyboard_controller/src/main/cpp/RNStatusBarManagerCompat.cpp +24 -0
  26. package/harmony/keyboard_controller/src/main/cpp/RNStatusBarManagerCompat.h +28 -0
  27. package/harmony/keyboard_controller/src/main/cpp/keyboardControllerPackage.cpp +43 -0
  28. package/harmony/keyboard_controller/src/main/cpp/keyboardControllerPackage.h +56 -0
  29. package/harmony/keyboard_controller/src/main/ets/Logger.ts +46 -0
  30. package/harmony/keyboard_controller/src/main/ets/RNKeyboardControllerPackage.ts +45 -0
  31. package/harmony/keyboard_controller/src/main/ets/RNKeyboardControllerTurboModule.ts +238 -0
  32. package/harmony/keyboard_controller/src/main/ets/RNStatusBarManagerCompatTurboModule.ts +98 -0
  33. package/harmony/keyboard_controller/src/main/ets/Type.ts +41 -0
  34. package/harmony/keyboard_controller/src/main/module.json5 +11 -0
  35. package/harmony/keyboard_controller/src/main/resources/base/element/string.json +8 -0
  36. package/harmony/keyboard_controller/src/main/resources/en_US/element/string.json +8 -0
  37. package/harmony/keyboard_controller/src/main/resources/zh_CN/element/string.json +8 -0
  38. package/harmony/keyboard_controller/ts.ts +9 -0
  39. package/harmony/keyboard_controller.har +0 -0
  40. package/lib/commonjs/animated.js +176 -0
  41. package/lib/commonjs/animated.js.map +1 -0
  42. package/lib/commonjs/bindings.js +39 -0
  43. package/lib/commonjs/bindings.js.map +1 -0
  44. package/lib/commonjs/bindings.native.js +39 -0
  45. package/lib/commonjs/bindings.native.js.map +1 -0
  46. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js +126 -0
  47. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js.map +1 -0
  48. package/lib/commonjs/components/KeyboardAvoidingView/index.js +120 -0
  49. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -0
  50. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +262 -0
  51. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -0
  52. package/lib/commonjs/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js +110 -0
  53. package/lib/commonjs/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -0
  54. package/lib/commonjs/components/KeyboardAwareScrollView/utils.js +37 -0
  55. package/lib/commonjs/components/KeyboardAwareScrollView/utils.js.map +1 -0
  56. package/lib/commonjs/components/KeyboardStickyView/index.js +41 -0
  57. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -0
  58. package/lib/commonjs/components/KeyboardToolbar/Arrow.js +76 -0
  59. package/lib/commonjs/components/KeyboardToolbar/Arrow.js.map +1 -0
  60. package/lib/commonjs/components/KeyboardToolbar/Button.js +70 -0
  61. package/lib/commonjs/components/KeyboardToolbar/Button.js.map +1 -0
  62. package/lib/commonjs/components/KeyboardToolbar/colors.js +21 -0
  63. package/lib/commonjs/components/KeyboardToolbar/colors.js.map +1 -0
  64. package/lib/commonjs/components/KeyboardToolbar/colors.native.js +40 -0
  65. package/lib/commonjs/components/KeyboardToolbar/colors.native.js.map +1 -0
  66. package/lib/commonjs/components/KeyboardToolbar/index.js +161 -0
  67. package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -0
  68. package/lib/commonjs/components/KeyboardToolbar/types.js +6 -0
  69. package/lib/commonjs/components/KeyboardToolbar/types.js.map +1 -0
  70. package/lib/commonjs/components/hooks/useColorScheme.js +10 -0
  71. package/lib/commonjs/components/hooks/useColorScheme.js.map +1 -0
  72. package/lib/commonjs/components/index.js +42 -0
  73. package/lib/commonjs/components/index.js.map +1 -0
  74. package/lib/commonjs/constants.js +27 -0
  75. package/lib/commonjs/constants.js.map +1 -0
  76. package/lib/commonjs/context.js +45 -0
  77. package/lib/commonjs/context.js.map +1 -0
  78. package/lib/commonjs/hooks/index.js +104 -0
  79. package/lib/commonjs/hooks/index.js.map +1 -0
  80. package/lib/commonjs/hooks/useWindowDimensions/index.android.js +34 -0
  81. package/lib/commonjs/hooks/useWindowDimensions/index.android.js.map +1 -0
  82. package/lib/commonjs/hooks/useWindowDimensions/index.js +13 -0
  83. package/lib/commonjs/hooks/useWindowDimensions/index.js.map +1 -0
  84. package/lib/commonjs/index.js +136 -0
  85. package/lib/commonjs/index.js.map +1 -0
  86. package/lib/commonjs/internal.js +73 -0
  87. package/lib/commonjs/internal.js.map +1 -0
  88. package/lib/commonjs/module.js +47 -0
  89. package/lib/commonjs/module.js.map +1 -0
  90. package/lib/commonjs/monkey-patch.android.js +57 -0
  91. package/lib/commonjs/monkey-patch.android.js.map +1 -0
  92. package/lib/commonjs/monkey-patch.js +11 -0
  93. package/lib/commonjs/monkey-patch.js.map +1 -0
  94. package/lib/commonjs/reanimated.js +12 -0
  95. package/lib/commonjs/reanimated.js.map +1 -0
  96. package/lib/commonjs/reanimated.native.js +88 -0
  97. package/lib/commonjs/reanimated.native.js.map +1 -0
  98. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js +10 -0
  99. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -0
  100. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js +12 -0
  101. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js.map +1 -0
  102. package/lib/commonjs/specs/NativeKeyboardController.js +9 -0
  103. package/lib/commonjs/specs/NativeKeyboardController.js.map +1 -0
  104. package/lib/commonjs/specs/NativeStatusBarManagerCompat.js +9 -0
  105. package/lib/commonjs/specs/NativeStatusBarManagerCompat.js.map +1 -0
  106. package/lib/commonjs/specs/OverKeyboardViewNativeComponent.js +10 -0
  107. package/lib/commonjs/specs/OverKeyboardViewNativeComponent.js.map +1 -0
  108. package/lib/commonjs/types.js +6 -0
  109. package/lib/commonjs/types.js.map +1 -0
  110. package/lib/commonjs/utils.js +9 -0
  111. package/lib/commonjs/utils.js.map +1 -0
  112. package/lib/commonjs/views/OverKeyboardView/index.js +42 -0
  113. package/lib/commonjs/views/OverKeyboardView/index.js.map +1 -0
  114. package/lib/commonjs/views/index.js +14 -0
  115. package/lib/commonjs/views/index.js.map +1 -0
  116. package/lib/module/animated.js +168 -0
  117. package/lib/module/animated.js.map +1 -0
  118. package/lib/module/bindings.js +33 -0
  119. package/lib/module/bindings.js.map +1 -0
  120. package/lib/module/bindings.native.js +33 -0
  121. package/lib/module/bindings.native.js.map +1 -0
  122. package/lib/module/components/KeyboardAvoidingView/hooks.js +118 -0
  123. package/lib/module/components/KeyboardAvoidingView/hooks.js.map +1 -0
  124. package/lib/module/components/KeyboardAvoidingView/index.js +113 -0
  125. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -0
  126. package/lib/module/components/KeyboardAwareScrollView/index.js +255 -0
  127. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -0
  128. package/lib/module/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js +103 -0
  129. package/lib/module/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -0
  130. package/lib/module/components/KeyboardAwareScrollView/utils.js +29 -0
  131. package/lib/module/components/KeyboardAwareScrollView/utils.js.map +1 -0
  132. package/lib/module/components/KeyboardStickyView/index.js +34 -0
  133. package/lib/module/components/KeyboardStickyView/index.js.map +1 -0
  134. package/lib/module/components/KeyboardToolbar/Arrow.js +68 -0
  135. package/lib/module/components/KeyboardToolbar/Arrow.js.map +1 -0
  136. package/lib/module/components/KeyboardToolbar/Button.js +62 -0
  137. package/lib/module/components/KeyboardToolbar/Button.js.map +1 -0
  138. package/lib/module/components/KeyboardToolbar/colors.js +15 -0
  139. package/lib/module/components/KeyboardToolbar/colors.js.map +1 -0
  140. package/lib/module/components/KeyboardToolbar/colors.native.js +34 -0
  141. package/lib/module/components/KeyboardToolbar/colors.native.js.map +1 -0
  142. package/lib/module/components/KeyboardToolbar/index.js +149 -0
  143. package/lib/module/components/KeyboardToolbar/index.js.map +1 -0
  144. package/lib/module/components/KeyboardToolbar/types.js +2 -0
  145. package/lib/module/components/KeyboardToolbar/types.js.map +1 -0
  146. package/lib/module/components/hooks/useColorScheme.js +4 -0
  147. package/lib/module/components/hooks/useColorScheme.js.map +1 -0
  148. package/lib/module/components/index.js +5 -0
  149. package/lib/module/components/index.js.map +1 -0
  150. package/lib/module/constants.js +21 -0
  151. package/lib/module/constants.js.map +1 -0
  152. package/lib/module/context.js +38 -0
  153. package/lib/module/context.js.map +1 -0
  154. package/lib/module/hooks/index.js +68 -0
  155. package/lib/module/hooks/index.js.map +1 -0
  156. package/lib/module/hooks/useWindowDimensions/index.android.js +27 -0
  157. package/lib/module/hooks/useWindowDimensions/index.android.js.map +1 -0
  158. package/lib/module/hooks/useWindowDimensions/index.js +2 -0
  159. package/lib/module/hooks/useWindowDimensions/index.js.map +1 -0
  160. package/lib/module/index.js +12 -0
  161. package/lib/module/index.js.map +1 -0
  162. package/lib/module/internal.js +66 -0
  163. package/lib/module/internal.js.map +1 -0
  164. package/lib/module/module.js +41 -0
  165. package/lib/module/module.js.map +1 -0
  166. package/lib/module/monkey-patch.android.js +47 -0
  167. package/lib/module/monkey-patch.android.js.map +1 -0
  168. package/lib/module/monkey-patch.js +5 -0
  169. package/lib/module/monkey-patch.js.map +1 -0
  170. package/lib/module/reanimated.js +6 -0
  171. package/lib/module/reanimated.js.map +1 -0
  172. package/lib/module/reanimated.native.js +78 -0
  173. package/lib/module/reanimated.native.js.map +1 -0
  174. package/lib/module/specs/KeyboardControllerViewNativeComponent.js +3 -0
  175. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -0
  176. package/lib/module/specs/KeyboardGestureAreaNativeComponent.js +5 -0
  177. package/lib/module/specs/KeyboardGestureAreaNativeComponent.js.map +1 -0
  178. package/lib/module/specs/NativeKeyboardController.js +3 -0
  179. package/lib/module/specs/NativeKeyboardController.js.map +1 -0
  180. package/lib/module/specs/NativeStatusBarManagerCompat.js +3 -0
  181. package/lib/module/specs/NativeStatusBarManagerCompat.js.map +1 -0
  182. package/lib/module/specs/OverKeyboardViewNativeComponent.js +3 -0
  183. package/lib/module/specs/OverKeyboardViewNativeComponent.js.map +1 -0
  184. package/lib/module/types.js +2 -0
  185. package/lib/module/types.js.map +1 -0
  186. package/lib/module/utils.js +2 -0
  187. package/lib/module/utils.js.map +1 -0
  188. package/lib/module/views/OverKeyboardView/index.js +35 -0
  189. package/lib/module/views/OverKeyboardView/index.js.map +1 -0
  190. package/lib/module/views/index.js +2 -0
  191. package/lib/module/views/index.js.map +1 -0
  192. package/lib/typescript/animated.d.ts +39 -0
  193. package/lib/typescript/bindings.d.ts +12 -0
  194. package/lib/typescript/bindings.native.d.ts +12 -0
  195. package/lib/typescript/components/KeyboardAvoidingView/hooks.d.ts +10 -0
  196. package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +40 -0
  197. package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +29 -0
  198. package/lib/typescript/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.d.ts +6 -0
  199. package/lib/typescript/components/KeyboardAwareScrollView/utils.d.ts +2 -0
  200. package/lib/typescript/components/KeyboardStickyView/index.d.ts +39 -0
  201. package/lib/typescript/components/KeyboardToolbar/Arrow.d.ts +9 -0
  202. package/lib/typescript/components/KeyboardToolbar/Button.d.ts +16 -0
  203. package/lib/typescript/components/KeyboardToolbar/colors.d.ts +2 -0
  204. package/lib/typescript/components/KeyboardToolbar/colors.native.d.ts +2 -0
  205. package/lib/typescript/components/KeyboardToolbar/index.d.ts +52 -0
  206. package/lib/typescript/components/KeyboardToolbar/types.d.ts +18 -0
  207. package/lib/typescript/components/hooks/useColorScheme.d.ts +2 -0
  208. package/lib/typescript/components/index.d.ts +8 -0
  209. package/lib/typescript/constants.d.ts +16 -0
  210. package/lib/typescript/context.d.ts +23 -0
  211. package/lib/typescript/hooks/index.d.ts +17 -0
  212. package/lib/typescript/hooks/useWindowDimensions/index.android.d.ts +2 -0
  213. package/lib/typescript/hooks/useWindowDimensions/index.d.ts +1 -0
  214. package/lib/typescript/index.d.ts +10 -0
  215. package/lib/typescript/internal.d.ts +30 -0
  216. package/lib/typescript/module.d.ts +2 -0
  217. package/lib/typescript/monkey-patch.android.d.ts +2 -0
  218. package/lib/typescript/monkey-patch.d.ts +2 -0
  219. package/lib/typescript/reanimated.d.ts +5 -0
  220. package/lib/typescript/reanimated.native.d.ts +7 -0
  221. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +54 -0
  222. package/lib/typescript/specs/KeyboardGestureAreaNativeComponent.d.ts +12 -0
  223. package/lib/typescript/specs/NativeKeyboardController.d.ts +12 -0
  224. package/lib/typescript/specs/NativeStatusBarManagerCompat.d.ts +10 -0
  225. package/lib/typescript/specs/OverKeyboardViewNativeComponent.d.ts +7 -0
  226. package/lib/typescript/types.d.ts +161 -0
  227. package/lib/typescript/utils.d.ts +1 -0
  228. package/lib/typescript/views/OverKeyboardView/index.d.ts +5 -0
  229. package/lib/typescript/views/index.d.ts +1 -0
  230. package/package.json +173 -0
  231. package/react-native-keyboard-controller.podspec +61 -0
  232. package/src/animated.tsx +256 -0
  233. package/src/bindings.native.ts +62 -0
  234. package/src/bindings.ts +42 -0
  235. package/src/components/KeyboardAvoidingView/hooks.ts +123 -0
  236. package/src/components/KeyboardAvoidingView/index.tsx +188 -0
  237. package/src/components/KeyboardAwareScrollView/index.tsx +389 -0
  238. package/src/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.ts +133 -0
  239. package/src/components/KeyboardAwareScrollView/utils.ts +41 -0
  240. package/src/components/KeyboardStickyView/index.tsx +66 -0
  241. package/src/components/KeyboardToolbar/Arrow.tsx +80 -0
  242. package/src/components/KeyboardToolbar/Button.tsx +98 -0
  243. package/src/components/KeyboardToolbar/colors.native.ts +37 -0
  244. package/src/components/KeyboardToolbar/colors.ts +16 -0
  245. package/src/components/KeyboardToolbar/index.tsx +223 -0
  246. package/src/components/KeyboardToolbar/types.ts +40 -0
  247. package/src/components/hooks/useColorScheme.ts +5 -0
  248. package/src/components/index.ts +11 -0
  249. package/src/constants.ts +19 -0
  250. package/src/context.ts +68 -0
  251. package/src/hooks/index.ts +90 -0
  252. package/src/hooks/useWindowDimensions/index.android.ts +38 -0
  253. package/src/hooks/useWindowDimensions/index.ts +1 -0
  254. package/src/index.ts +23 -0
  255. package/src/internal.ts +84 -0
  256. package/src/module.ts +52 -0
  257. package/src/monkey-patch.android.ts +44 -0
  258. package/src/monkey-patch.ts +4 -0
  259. package/src/reanimated.native.ts +132 -0
  260. package/src/reanimated.ts +29 -0
  261. package/src/specs/KeyboardControllerViewNativeComponent.ts +71 -0
  262. package/src/specs/KeyboardGestureAreaNativeComponent.ts +20 -0
  263. package/src/specs/NativeKeyboardController.ts +19 -0
  264. package/src/specs/NativeStatusBarManagerCompat.ts +14 -0
  265. package/src/specs/OverKeyboardViewNativeComponent.ts +12 -0
  266. package/src/types.ts +243 -0
  267. package/src/utils.ts +1 -0
  268. package/src/views/OverKeyboardView/index.tsx +43 -0
  269. package/src/views/index.ts +1 -0
@@ -0,0 +1,133 @@
1
+ import { Platform } from "react-native";
2
+ import {
3
+ Easing,
4
+ useAnimatedReaction,
5
+ useSharedValue,
6
+ withTiming,
7
+ } from "react-native-reanimated";
8
+
9
+ import { useKeyboardHandler } from "../../hooks";
10
+
11
+ const IS_ANDROID_ELEVEN_OR_HIGHER =
12
+ Platform.OS === "android" && Platform.Version >= 30;
13
+ // on these platforms keyboard transitions will be smooth
14
+ const IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS =
15
+ IS_ANDROID_ELEVEN_OR_HIGHER || Platform.OS === "ios" || Platform.OS as string === 'harmony';
16
+ // on Android Telegram is not using androidx.core values and uses custom interpolation
17
+ // duration is taken from here: https://github.com/DrKLO/Telegram/blob/e9a35cea54c06277c69d41b8e25d94b5d7ede065/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java#L39
18
+ // and bezier is taken from: https://github.com/DrKLO/Telegram/blob/e9a35cea54c06277c69d41b8e25d94b5d7ede065/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java#L40
19
+ const TELEGRAM_ANDROID_TIMING_CONFIG = {
20
+ duration: 250,
21
+ easing: Easing.bezier(
22
+ 0.19919472913616398,
23
+ 0.010644531250000006,
24
+ 0.27920937042459737,
25
+ 0.91025390625,
26
+ ),
27
+ };
28
+
29
+ /**
30
+ * Hook that uses default transitions for iOS and Android > 11, and uses
31
+ * custom interpolation on Android < 11 to achieve more smooth animation
32
+ */
33
+ export const useSmoothKeyboardHandler: typeof useKeyboardHandler = (
34
+ handler,
35
+ deps,
36
+ ) => {
37
+ const target = useSharedValue(-1);
38
+ const height = useSharedValue(0);
39
+ const persistedHeight = useSharedValue(0);
40
+ const animatedKeyboardHeight = useSharedValue(0);
41
+
42
+ useAnimatedReaction(
43
+ () => {
44
+ if (IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) {
45
+ return;
46
+ }
47
+ if (persistedHeight.value === 0) {
48
+ return;
49
+ }
50
+ const event = {
51
+ // it'll be always `TELEGRAM_ANDROID_TIMING_CONFIG.duration`, since we're running animation via `withTiming`
52
+ duration: TELEGRAM_ANDROID_TIMING_CONFIG.duration,
53
+ target: target.value,
54
+ height: animatedKeyboardHeight.value,
55
+ progress: animatedKeyboardHeight.value / persistedHeight.value,
56
+ };
57
+ return event;
58
+ },
59
+ (evt) => {
60
+ if (!evt) {
61
+ return;
62
+ }
63
+ handler.onMove?.(evt);
64
+
65
+ // dispatch `onEnd`
66
+ if (evt.height === height.value) {
67
+ handler.onEnd?.(evt);
68
+ // eslint-disable-next-line react-compiler/react-compiler
69
+ persistedHeight.value = height.value;
70
+ }
71
+ },
72
+ // REA uses own version of `DependencyList` and it's not compatible with the same type from React
73
+ deps as unknown[],
74
+ );
75
+
76
+ useKeyboardHandler(
77
+ {
78
+ onStart: (e) => {
79
+ "worklet";
80
+
81
+ // immediately dispatch onStart/onEnd events if onStart dispatched with the same height
82
+ // and don't wait for animation 250ms
83
+ if (
84
+ !IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS &&
85
+ e.height === persistedHeight.value
86
+ ) {
87
+ handler.onStart?.(e);
88
+ handler.onEnd?.(e);
89
+
90
+ return;
91
+ }
92
+
93
+ target.value = e.target;
94
+ height.value = e.height;
95
+
96
+ if (e.height > 0) {
97
+ persistedHeight.value = e.height;
98
+ }
99
+ // if we are running on Android < 9, then we are using custom interpolation
100
+ // to achieve smoother animation and use `animatedKeyboardHeight` as animation
101
+ // driver
102
+ if (!IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) {
103
+ animatedKeyboardHeight.value = withTiming(
104
+ e.height,
105
+ TELEGRAM_ANDROID_TIMING_CONFIG,
106
+ );
107
+ }
108
+
109
+ handler.onStart?.({
110
+ ...e,
111
+ duration: IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS
112
+ ? e.duration
113
+ : TELEGRAM_ANDROID_TIMING_CONFIG.duration,
114
+ });
115
+ },
116
+ onMove: (e) => {
117
+ "worklet";
118
+
119
+ if (IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) {
120
+ handler.onMove?.(e);
121
+ }
122
+ },
123
+ onEnd: (e) => {
124
+ "worklet";
125
+
126
+ if (IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) {
127
+ handler.onEnd?.(e);
128
+ }
129
+ },
130
+ },
131
+ deps,
132
+ );
133
+ };
@@ -0,0 +1,41 @@
1
+ export const debounce = <F extends (...args: Parameters<F>) => ReturnType<F>>(
2
+ worklet: F,
3
+ wait = 0,
4
+ ) => {
5
+ "worklet";
6
+
7
+ const value = {
8
+ time: 0,
9
+ };
10
+
11
+ return (...args: Parameters<F>): ReturnType<F> | void => {
12
+ "worklet";
13
+
14
+ const t = Date.now();
15
+ const now = t - value.time;
16
+
17
+ if (now < wait) {
18
+ value.time = t;
19
+ return;
20
+ }
21
+
22
+ value.time = t;
23
+
24
+ return worklet(...args);
25
+ };
26
+ };
27
+
28
+ export const scrollDistanceWithRespectToSnapPoints = (
29
+ defaultScrollValue: number,
30
+ snapPoints?: number[],
31
+ ) => {
32
+ "worklet";
33
+
34
+ let snapPoint: number | undefined;
35
+
36
+ if (snapPoints) {
37
+ snapPoint = snapPoints.find((offset) => offset >= defaultScrollValue);
38
+ }
39
+
40
+ return snapPoint ?? defaultScrollValue;
41
+ };
@@ -0,0 +1,66 @@
1
+ import React, { forwardRef, useMemo } from "react";
2
+ import Reanimated, {
3
+ interpolate,
4
+ useAnimatedStyle,
5
+ } from "react-native-reanimated";
6
+
7
+ import { useReanimatedKeyboardAnimation } from "../../hooks";
8
+
9
+ import type { View, ViewProps } from "react-native";
10
+
11
+ export type KeyboardStickyViewProps = {
12
+ /**
13
+ * Specify additional offset to the view for given keyboard state.
14
+ */
15
+ offset?: {
16
+ /**
17
+ * Adds additional `translateY` when keyboard is close. By default `0`.
18
+ */
19
+ closed?: number;
20
+ /**
21
+ * Adds additional `translateY` when keyboard is open. By default `0`.
22
+ */
23
+ opened?: number;
24
+ };
25
+
26
+ /** Controls whether this `KeyboardStickyView` instance should take effect. Default is `true` */
27
+ enabled?: boolean;
28
+ } & ViewProps;
29
+
30
+ const KeyboardStickyView = forwardRef<
31
+ View,
32
+ React.PropsWithChildren<KeyboardStickyViewProps>
33
+ >(
34
+ (
35
+ {
36
+ children,
37
+ offset: { closed = 0, opened = 0 } = {},
38
+ style,
39
+ enabled = true,
40
+ ...props
41
+ },
42
+ ref,
43
+ ) => {
44
+ const { height, progress } = useReanimatedKeyboardAnimation();
45
+ const stickyViewStyle = useAnimatedStyle(() => {
46
+ const offset = interpolate(progress.value, [0, 1], [closed, opened]);
47
+
48
+ return {
49
+ transform: [{ translateY: enabled ? height.value + offset : closed }],
50
+ };
51
+ }, [closed, opened, enabled]);
52
+
53
+ const styles = useMemo(
54
+ () => [style, stickyViewStyle],
55
+ [style, stickyViewStyle],
56
+ );
57
+
58
+ return (
59
+ <Reanimated.View ref={ref} style={styles} {...props}>
60
+ {children}
61
+ </Reanimated.View>
62
+ );
63
+ },
64
+ );
65
+
66
+ export default KeyboardStickyView;
@@ -0,0 +1,80 @@
1
+ import React, { useMemo } from "react";
2
+ import { Animated, StyleSheet, View } from "react-native";
3
+
4
+ import useColorScheme from "../hooks/useColorScheme";
5
+
6
+ import type { KeyboardToolbarTheme } from "./types";
7
+ import type { ViewStyle } from "react-native";
8
+
9
+ type ArrowProps = {
10
+ type: "prev" | "next";
11
+ disabled?: boolean;
12
+ theme: KeyboardToolbarTheme;
13
+ };
14
+
15
+ const ArrowComponent: React.FC<ArrowProps> = ({ type, disabled, theme }) => {
16
+ const colorScheme = useColorScheme();
17
+
18
+ const color = useMemo(
19
+ () => ({
20
+ backgroundColor: disabled
21
+ ? theme[colorScheme].disabled
22
+ : theme[colorScheme].primary,
23
+ }),
24
+ [disabled, theme, colorScheme],
25
+ );
26
+ const left = useMemo(() => [styles.arrowLeftLine, color], [color]);
27
+ const right = useMemo(() => [styles.arrowRightLine, color], [color]);
28
+
29
+ return (
30
+ <View
31
+ style={
32
+ type === "next" ? styles.arrowDownContainer : styles.arrowUpContainer
33
+ }
34
+ >
35
+ <View style={styles.arrow}>
36
+ <Animated.View style={left} />
37
+ <Animated.View style={right} />
38
+ </View>
39
+ </View>
40
+ );
41
+ };
42
+
43
+ const arrowLine: ViewStyle = {
44
+ width: 13,
45
+ height: 2,
46
+ borderRadius: 1,
47
+ };
48
+ const arrowUpContainer: ViewStyle = {
49
+ marginHorizontal: 5,
50
+ width: 30,
51
+ height: 30,
52
+ justifyContent: "center",
53
+ alignItems: "center",
54
+ };
55
+ const styles = StyleSheet.create({
56
+ arrowUpContainer: arrowUpContainer,
57
+ arrowDownContainer: {
58
+ ...arrowUpContainer,
59
+ transform: [{ rotate: "180deg" }],
60
+ },
61
+ arrow: {
62
+ width: 20,
63
+ height: 20,
64
+ flexDirection: "row",
65
+ alignItems: "center",
66
+ justifyContent: "space-between",
67
+ },
68
+ arrowLeftLine: {
69
+ ...arrowLine,
70
+ transform: [{ rotate: "-45deg" }],
71
+ left: -0.5,
72
+ },
73
+ arrowRightLine: {
74
+ ...arrowLine,
75
+ transform: [{ rotate: "45deg" }],
76
+ left: -5.5,
77
+ },
78
+ });
79
+
80
+ export default ArrowComponent;
@@ -0,0 +1,98 @@
1
+ import React, { useMemo } from "react";
2
+ import {
3
+ Platform,
4
+ TouchableNativeFeedback,
5
+ TouchableOpacity,
6
+ View,
7
+ } from "react-native";
8
+
9
+ import useColorScheme from "../hooks/useColorScheme";
10
+
11
+ import type { KeyboardToolbarTheme } from "./types";
12
+ import type { PropsWithChildren } from "react";
13
+ import type { ViewStyle } from "react-native";
14
+
15
+ type ButtonProps = {
16
+ disabled?: boolean;
17
+ onPress: () => void;
18
+ accessibilityLabel: string;
19
+ accessibilityHint: string;
20
+ testID: string;
21
+ rippleRadius?: number;
22
+ style?: ViewStyle;
23
+ theme: KeyboardToolbarTheme;
24
+ };
25
+
26
+ const ButtonIOS = ({
27
+ children,
28
+ onPress,
29
+ disabled,
30
+ accessibilityLabel,
31
+ accessibilityHint,
32
+ testID,
33
+ style,
34
+ }: PropsWithChildren<ButtonProps>) => {
35
+ // immediately switch to plain view to avoid animation flickering
36
+ // when fade out animation happens and view becomes disabled
37
+ const Container = disabled
38
+ ? (View as unknown as typeof TouchableOpacity)
39
+ : TouchableOpacity;
40
+ const accessibilityState = useMemo(() => ({ disabled }), [disabled]);
41
+
42
+ return (
43
+ <Container
44
+ accessibilityState={accessibilityState}
45
+ accessibilityRole="button"
46
+ accessibilityLabel={accessibilityLabel}
47
+ accessibilityHint={accessibilityHint}
48
+ onPress={onPress}
49
+ style={style}
50
+ testID={testID}
51
+ >
52
+ {children}
53
+ </Container>
54
+ );
55
+ };
56
+ const ButtonAndroid = ({
57
+ children,
58
+ onPress,
59
+ disabled,
60
+ accessibilityLabel,
61
+ accessibilityHint,
62
+ testID,
63
+ rippleRadius = 18,
64
+ style,
65
+ theme,
66
+ }: PropsWithChildren<ButtonProps>) => {
67
+ const colorScheme = useColorScheme();
68
+ const accessibilityState = useMemo(() => ({ disabled }), [disabled]);
69
+ const ripple = useMemo(
70
+ () =>
71
+ TouchableNativeFeedback.Ripple(
72
+ theme[colorScheme].ripple,
73
+ true,
74
+ rippleRadius,
75
+ ),
76
+ [colorScheme, rippleRadius, theme],
77
+ );
78
+
79
+ return (
80
+ <TouchableNativeFeedback
81
+ accessibilityState={accessibilityState}
82
+ accessibilityRole="button"
83
+ accessibilityLabel={accessibilityLabel}
84
+ accessibilityHint={accessibilityHint}
85
+ onPress={onPress}
86
+ background={ripple}
87
+ testID={testID}
88
+ style={style}
89
+ >
90
+ <View style={style}>{children}</View>
91
+ </TouchableNativeFeedback>
92
+ );
93
+ };
94
+
95
+ export default Platform.select({
96
+ android: ButtonAndroid,
97
+ default: ButtonIOS,
98
+ });
@@ -0,0 +1,37 @@
1
+ import { Platform, PlatformColor } from "react-native";
2
+
3
+ import type { KeyboardToolbarTheme } from "./types";
4
+ import type { ColorValue } from "react-native";
5
+
6
+ export const colors: KeyboardToolbarTheme = {
7
+ light: {
8
+ primary: Platform.select<ColorValue>({
9
+ ios: PlatformColor("link"),
10
+ default: "#2c2c2c",
11
+ }),
12
+ disabled: Platform.select<ColorValue>({
13
+ ios: PlatformColor("systemGray4"),
14
+ default: "#B0BEC5",
15
+ }),
16
+ background: Platform.select({
17
+ ios: "#F8F8F8",
18
+ default: "#f3f3f4",
19
+ }),
20
+ ripple: "#bcbcbcbc",
21
+ },
22
+ dark: {
23
+ primary: Platform.select<ColorValue>({
24
+ ios: PlatformColor("label"),
25
+ default: "#fafafa",
26
+ }),
27
+ disabled: Platform.select<ColorValue>({
28
+ ios: PlatformColor("systemGray"),
29
+ default: "#707070",
30
+ }),
31
+ background: Platform.select({
32
+ ios: "#555756",
33
+ default: "#2C2C2E",
34
+ }),
35
+ ripple: "#F8F8F888",
36
+ },
37
+ };
@@ -0,0 +1,16 @@
1
+ import type { KeyboardToolbarTheme } from "./types";
2
+
3
+ export const colors: KeyboardToolbarTheme = {
4
+ light: {
5
+ primary: "#2c2c2c",
6
+ disabled: "#B0BEC5",
7
+ background: "#f3f3f4",
8
+ ripple: "#bcbcbcbc",
9
+ },
10
+ dark: {
11
+ primary: "#fafafa",
12
+ disabled: "#707070",
13
+ background: "#2C2C2E",
14
+ ripple: "#F8F8F888",
15
+ },
16
+ };
@@ -0,0 +1,223 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { StyleSheet, Text, View } from "react-native";
3
+
4
+ import {
5
+ FocusedInputEvents,
6
+ } from "../../bindings";
7
+ import KeyboardStickyView from "../KeyboardStickyView"
8
+ import { KeyboardControllerNative } from "../../bindings";
9
+ import useColorScheme from "../hooks/useColorScheme";
10
+
11
+ import Arrow from "./Arrow";
12
+ import Button from "./Button";
13
+ import { colors } from "./colors";
14
+
15
+ import type { HEX, KeyboardToolbarTheme } from "./types";
16
+ import type { KeyboardStickyViewProps } from "../KeyboardStickyView";
17
+ import type { ReactNode } from "react";
18
+ import type { ViewProps } from "react-native";
19
+
20
+ export type KeyboardToolbarProps = Omit<
21
+ ViewProps,
22
+ "style" | "testID" | "children"
23
+ > & {
24
+ /** An element that is shown in the middle of the toolbar. */
25
+ content?: JSX.Element | null;
26
+ /** A set of dark/light colors consumed by toolbar component. */
27
+ theme?: KeyboardToolbarTheme;
28
+ /** Custom text for done button. */
29
+ doneText?: ReactNode;
30
+ /** Custom touchable component for toolbar (used for prev/next/done buttons). */
31
+ button?: typeof Button;
32
+ /** Custom icon component used to display next/prev buttons. */
33
+ icon?: typeof Arrow;
34
+ /**
35
+ * Whether to show next and previous buttons. Can be useful to set it to `false` if you have only one input
36
+ * and want to show only `Done` button. Default to `true`.
37
+ */
38
+ showArrows?: boolean;
39
+ /**
40
+ * A callback that is called when the user presses the next button along with the default action.
41
+ */
42
+ onNextCallback?: () => void;
43
+ /**
44
+ * A callback that is called when the user presses the previous button along with the default action.
45
+ */
46
+ onPrevCallback?: () => void;
47
+ /**
48
+ * A callback that is called when the user presses the done button along with the default action.
49
+ */
50
+ onDoneCallback?: () => void;
51
+ /**
52
+ * A component that applies blur effect to the toolbar.
53
+ */
54
+ blur?: JSX.Element | null;
55
+ /**
56
+ * A value for container opacity in hexadecimal format (e.g. `ff`). Default value is `ff`.
57
+ */
58
+ opacity?: HEX;
59
+ } & Pick<KeyboardStickyViewProps, "offset" | "enabled">;
60
+
61
+ const TEST_ID_KEYBOARD_TOOLBAR = "keyboard.toolbar";
62
+ const TEST_ID_KEYBOARD_TOOLBAR_PREVIOUS = `${TEST_ID_KEYBOARD_TOOLBAR}.previous`;
63
+ const TEST_ID_KEYBOARD_TOOLBAR_NEXT = `${TEST_ID_KEYBOARD_TOOLBAR}.next`;
64
+ const TEST_ID_KEYBOARD_TOOLBAR_CONTENT = `${TEST_ID_KEYBOARD_TOOLBAR}.content`;
65
+ const TEST_ID_KEYBOARD_TOOLBAR_DONE = `${TEST_ID_KEYBOARD_TOOLBAR}.done`;
66
+
67
+ const KEYBOARD_TOOLBAR_HEIGHT = 42;
68
+ const DEFAULT_OPACITY: HEX = "FF";
69
+
70
+ const dismissKeyboard = () => KeyboardControllerNative.dismiss(false);
71
+ const goToNextField = () => KeyboardControllerNative.setFocusTo("next");
72
+ const goToPrevField = () => KeyboardControllerNative.setFocusTo("prev");
73
+
74
+ /**
75
+ * `KeyboardToolbar` is a component that is shown above the keyboard with `Prev`/`Next` and
76
+ * `Done` buttons.
77
+ */
78
+ const KeyboardToolbar: React.FC<KeyboardToolbarProps> = ({
79
+ content,
80
+ theme = colors,
81
+ doneText,
82
+ button,
83
+ icon,
84
+ showArrows = true,
85
+ onNextCallback,
86
+ onPrevCallback,
87
+ onDoneCallback,
88
+ blur = null,
89
+ opacity = DEFAULT_OPACITY,
90
+ offset: { closed = 0, opened = 0 } = {},
91
+ enabled = true,
92
+ ...rest
93
+ }) => {
94
+ const colorScheme = useColorScheme();
95
+ const [inputs, setInputs] = useState({
96
+ current: 0,
97
+ count: 0,
98
+ });
99
+ const isPrevDisabled = inputs.current === 0;
100
+ const isNextDisabled = inputs.current === inputs.count - 1;
101
+
102
+ useEffect(() => {
103
+ const subscription = FocusedInputEvents.addListener("focusDidSet", (e) => {
104
+ setInputs(e);
105
+ });
106
+
107
+ return subscription.remove;
108
+ }, []);
109
+ const doneStyle = useMemo(
110
+ () => [styles.doneButton, { color: theme[colorScheme].primary }],
111
+ [colorScheme, theme],
112
+ );
113
+ const toolbarStyle = useMemo(
114
+ () => [
115
+ styles.toolbar,
116
+ {
117
+ backgroundColor: `${theme[colorScheme].background}${opacity}`,
118
+ },
119
+ ],
120
+ [colorScheme, opacity, theme],
121
+ );
122
+ const offset = useMemo(
123
+ () => ({ closed: closed + KEYBOARD_TOOLBAR_HEIGHT, opened }),
124
+ [closed, opened],
125
+ );
126
+ const ButtonContainer = button || Button;
127
+ const IconContainer = icon || Arrow;
128
+
129
+ const onPressNext = useCallback(() => {
130
+ goToNextField();
131
+ onNextCallback?.();
132
+ }, [onNextCallback]);
133
+ const onPressPrev = useCallback(() => {
134
+ goToPrevField();
135
+ onPrevCallback?.();
136
+ }, [onPrevCallback]);
137
+ const onPressDone = useCallback(() => {
138
+ dismissKeyboard();
139
+ onDoneCallback?.();
140
+ }, [onDoneCallback]);
141
+
142
+ return (
143
+ <KeyboardStickyView enabled={enabled} offset={offset}>
144
+ <View {...rest} style={toolbarStyle} testID={TEST_ID_KEYBOARD_TOOLBAR}>
145
+ {blur}
146
+ {showArrows && (
147
+ <>
148
+ <ButtonContainer
149
+ accessibilityLabel="Previous"
150
+ accessibilityHint="Will move focus to previous field"
151
+ disabled={isPrevDisabled}
152
+ onPress={onPressPrev}
153
+ testID={TEST_ID_KEYBOARD_TOOLBAR_PREVIOUS}
154
+ theme={theme}
155
+ >
156
+ <IconContainer
157
+ disabled={isPrevDisabled}
158
+ type="prev"
159
+ theme={theme}
160
+ />
161
+ </ButtonContainer>
162
+ <ButtonContainer
163
+ accessibilityLabel="Next"
164
+ accessibilityHint="Will move focus to next field"
165
+ disabled={isNextDisabled}
166
+ onPress={onPressNext}
167
+ testID={TEST_ID_KEYBOARD_TOOLBAR_NEXT}
168
+ theme={theme}
169
+ >
170
+ <IconContainer
171
+ disabled={isNextDisabled}
172
+ type="next"
173
+ theme={theme}
174
+ />
175
+ </ButtonContainer>
176
+ </>
177
+ )}
178
+
179
+ <View style={styles.flex} testID={TEST_ID_KEYBOARD_TOOLBAR_CONTENT}>
180
+ {content}
181
+ </View>
182
+ <ButtonContainer
183
+ accessibilityLabel="Done"
184
+ accessibilityHint="Will close the keyboard"
185
+ onPress={onPressDone}
186
+ testID={TEST_ID_KEYBOARD_TOOLBAR_DONE}
187
+ rippleRadius={28}
188
+ style={styles.doneButtonContainer}
189
+ theme={theme}
190
+ >
191
+ <Text style={doneStyle} maxFontSizeMultiplier={1.3}>
192
+ {doneText || "Done"}
193
+ </Text>
194
+ </ButtonContainer>
195
+ </View>
196
+ </KeyboardStickyView>
197
+ );
198
+ };
199
+
200
+ const styles = StyleSheet.create({
201
+ flex: {
202
+ flex: 1,
203
+ },
204
+ toolbar: {
205
+ position: "absolute",
206
+ bottom: 0,
207
+ alignItems: "center",
208
+ width: "100%",
209
+ flexDirection: "row",
210
+ height: KEYBOARD_TOOLBAR_HEIGHT,
211
+ paddingHorizontal: 8,
212
+ },
213
+ doneButton: {
214
+ fontWeight: "600",
215
+ fontSize: 15,
216
+ },
217
+ doneButtonContainer: {
218
+ marginRight: 8,
219
+ },
220
+ });
221
+
222
+ export { colors as DefaultKeyboardToolbarTheme };
223
+ export default KeyboardToolbar;