react-native-keyboard-controller 1.10.6 → 1.11.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 (109) hide show
  1. package/README.md +1 -0
  2. package/android/build.gradle +6 -0
  3. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +4 -0
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputLayoutChangedEvent.kt +2 -0
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/EditText.kt +22 -0
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +9 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +20 -0
  8. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +7 -13
  9. package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +15 -0
  10. package/android/src/main/java/com/reactnativekeyboardcontroller/traversal/FocusedInputHolder.kt +16 -0
  11. package/android/src/main/java/com/reactnativekeyboardcontroller/traversal/ViewHierarchyNavigator.kt +101 -0
  12. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +5 -0
  13. package/android/src/test/java/com/reactnativekeyboardcontroller/traversal/ViewHierarchyNavigatorTest.kt +188 -0
  14. package/ios/.swiftlint.yml +4 -0
  15. package/ios/Extensions.swift +29 -0
  16. package/ios/KeyboardController.xcodeproj/project.pbxproj +20 -0
  17. package/ios/KeyboardControllerModule.mm +18 -0
  18. package/ios/events/FocusedInputLayoutChangedEvent.m +3 -0
  19. package/ios/observers/FocusedInputObserver.swift +20 -4
  20. package/ios/observers/KeyboardMovementObserver.swift +5 -4
  21. package/ios/traversal/FocusedInputHolder.swift +32 -0
  22. package/ios/traversal/TextInput.swift +26 -0
  23. package/ios/traversal/ViewHierarchyNavigator.swift +116 -0
  24. package/ios/views/KeyboardControllerView.mm +5 -0
  25. package/ios/views/KeyboardControllerViewManager.swift +4 -1
  26. package/jest/index.js +20 -0
  27. package/lib/commonjs/bindings.js +12 -1
  28. package/lib/commonjs/bindings.js.map +1 -1
  29. package/lib/commonjs/bindings.native.js +11 -2
  30. package/lib/commonjs/bindings.native.js.map +1 -1
  31. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +18 -6
  32. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
  33. package/lib/commonjs/components/KeyboardToolbar/Arrow.js +79 -0
  34. package/lib/commonjs/components/KeyboardToolbar/Arrow.js.map +1 -0
  35. package/lib/commonjs/components/KeyboardToolbar/Button.js +74 -0
  36. package/lib/commonjs/components/KeyboardToolbar/Button.js.map +1 -0
  37. package/lib/commonjs/components/KeyboardToolbar/colors.js +41 -0
  38. package/lib/commonjs/components/KeyboardToolbar/colors.js.map +1 -0
  39. package/lib/commonjs/components/KeyboardToolbar/index.js +136 -0
  40. package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -0
  41. package/lib/commonjs/components/hooks/useColorScheme.js +11 -0
  42. package/lib/commonjs/components/hooks/useColorScheme.js.map +1 -0
  43. package/lib/commonjs/components/hooks/useKeyboardInterpolation.js +3 -2
  44. package/lib/commonjs/components/hooks/useKeyboardInterpolation.js.map +1 -1
  45. package/lib/commonjs/components/index.js +21 -0
  46. package/lib/commonjs/components/index.js.map +1 -1
  47. package/lib/commonjs/index.js +22 -13
  48. package/lib/commonjs/index.js.map +1 -1
  49. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  50. package/lib/commonjs/specs/NativeKeyboardController.js.map +1 -1
  51. package/lib/commonjs/types.js.map +1 -1
  52. package/lib/module/bindings.js +10 -0
  53. package/lib/module/bindings.js.map +1 -1
  54. package/lib/module/bindings.native.js +9 -1
  55. package/lib/module/bindings.native.js.map +1 -1
  56. package/lib/module/components/KeyboardAwareScrollView/index.js +18 -6
  57. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
  58. package/lib/module/components/KeyboardToolbar/Arrow.js +69 -0
  59. package/lib/module/components/KeyboardToolbar/Arrow.js.map +1 -0
  60. package/lib/module/components/KeyboardToolbar/Button.js +64 -0
  61. package/lib/module/components/KeyboardToolbar/Button.js.map +1 -0
  62. package/lib/module/components/KeyboardToolbar/colors.js +34 -0
  63. package/lib/module/components/KeyboardToolbar/colors.js.map +1 -0
  64. package/lib/module/components/KeyboardToolbar/index.js +121 -0
  65. package/lib/module/components/KeyboardToolbar/index.js.map +1 -0
  66. package/lib/module/components/hooks/useColorScheme.js +4 -0
  67. package/lib/module/components/hooks/useColorScheme.js.map +1 -0
  68. package/lib/module/components/hooks/useKeyboardInterpolation.js +3 -2
  69. package/lib/module/components/hooks/useKeyboardInterpolation.js.map +1 -1
  70. package/lib/module/components/index.js +1 -0
  71. package/lib/module/components/index.js.map +1 -1
  72. package/lib/module/index.js +3 -2
  73. package/lib/module/index.js.map +1 -1
  74. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  75. package/lib/module/specs/NativeKeyboardController.js.map +1 -1
  76. package/lib/module/types.js.map +1 -1
  77. package/lib/typescript/bindings.d.ts +6 -1
  78. package/lib/typescript/bindings.native.d.ts +6 -1
  79. package/lib/typescript/components/KeyboardToolbar/Arrow.d.ts +9 -0
  80. package/lib/typescript/components/KeyboardToolbar/Button.d.ts +15 -0
  81. package/lib/typescript/components/KeyboardToolbar/colors.d.ts +17 -0
  82. package/lib/typescript/components/KeyboardToolbar/index.d.ts +25 -0
  83. package/lib/typescript/components/hooks/useColorScheme.d.ts +2 -0
  84. package/lib/typescript/components/index.d.ts +1 -0
  85. package/lib/typescript/index.d.ts +1 -2
  86. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +1 -0
  87. package/lib/typescript/specs/NativeKeyboardController.d.ts +1 -0
  88. package/lib/typescript/types.d.ts +11 -0
  89. package/package.json +5 -1
  90. package/src/bindings.native.ts +11 -1
  91. package/src/bindings.ts +9 -0
  92. package/src/components/KeyboardAwareScrollView/index.tsx +22 -2
  93. package/src/components/KeyboardToolbar/Arrow.tsx +80 -0
  94. package/src/components/KeyboardToolbar/Button.tsx +98 -0
  95. package/src/components/KeyboardToolbar/colors.ts +51 -0
  96. package/src/components/KeyboardToolbar/index.tsx +154 -0
  97. package/src/components/hooks/useColorScheme.ts +5 -0
  98. package/src/components/hooks/useKeyboardInterpolation.ts +3 -2
  99. package/src/components/index.ts +5 -0
  100. package/src/index.ts +4 -1
  101. package/src/specs/KeyboardControllerViewNativeComponent.ts +1 -0
  102. package/src/specs/NativeKeyboardController.ts +1 -0
  103. package/src/types.ts +14 -0
  104. package/lib/commonjs/replicas.js +0 -125
  105. package/lib/commonjs/replicas.js.map +0 -1
  106. package/lib/module/replicas.js +0 -115
  107. package/lib/module/replicas.js.map +0 -1
  108. package/lib/typescript/replicas.d.ts +0 -38
  109. package/src/replicas.ts +0 -154
@@ -7,11 +7,14 @@
7
7
  objects = {
8
8
 
9
9
  /* Begin PBXBuildFile section */
10
+ 0800511C2B65548600928E51 /* FocusedInputHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0800511B2B65548600928E51 /* FocusedInputHolder.swift */; };
11
+ 0800511E2B65558800928E51 /* TextInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0800511D2B65558800928E51 /* TextInput.swift */; };
10
12
  0807071E2A34807B00C05A19 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0807071D2A34807B00C05A19 /* Extensions.swift */; };
11
13
  083FB9852B15171600C0EFF0 /* TextChangeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083FB9842B15171600C0EFF0 /* TextChangeObserver.swift */; };
12
14
  083FB9872B15174C00C0EFF0 /* FocusedInputTextChangedEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 083FB9862B15174C00C0EFF0 /* FocusedInputTextChangedEvent.m */; };
13
15
  084AEEC62ACF49A8001A3069 /* FocusedInputLayoutChangedEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 084AEEC52ACF49A8001A3069 /* FocusedInputLayoutChangedEvent.m */; };
14
16
  084AEEC82ACF4AB2001A3069 /* FocusedInputObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 084AEEC72ACF4AB2001A3069 /* FocusedInputObserver.swift */; };
17
+ 089BA5DC2B3E0C9D000A9A90 /* ViewHierarchyNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 089BA5DB2B3E0C9D000A9A90 /* ViewHierarchyNavigator.swift */; };
15
18
  F333F8D428996B8D0015B05F /* KeyboardControllerView.mm in Sources */ = {isa = PBXBuildFile; fileRef = F333F8D228996B8D0015B05F /* KeyboardControllerView.mm */; };
16
19
  F359D34F28133C26000B6AFE /* KeyboardControllerModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = F359D34E28133C26000B6AFE /* KeyboardControllerModule.mm */; };
17
20
  F3626A0728B3FE760021B2D9 /* KeyboardMovementObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3626A0628B3FE760021B2D9 /* KeyboardMovementObserver.swift */; };
@@ -32,6 +35,8 @@
32
35
  /* End PBXCopyFilesBuildPhase section */
33
36
 
34
37
  /* Begin PBXFileReference section */
38
+ 0800511B2B65548600928E51 /* FocusedInputHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FocusedInputHolder.swift; sourceTree = "<group>"; };
39
+ 0800511D2B65558800928E51 /* TextInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextInput.swift; sourceTree = "<group>"; };
35
40
  0807071D2A34807B00C05A19 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
36
41
  083FB9842B15171600C0EFF0 /* TextChangeObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextChangeObserver.swift; sourceTree = "<group>"; };
37
42
  083FB9862B15174C00C0EFF0 /* FocusedInputTextChangedEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FocusedInputTextChangedEvent.m; sourceTree = "<group>"; };
@@ -39,6 +44,7 @@
39
44
  084AEEC22ACF479A001A3069 /* FocusedInputLayoutChangedEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FocusedInputLayoutChangedEvent.h; sourceTree = "<group>"; };
40
45
  084AEEC52ACF49A8001A3069 /* FocusedInputLayoutChangedEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FocusedInputLayoutChangedEvent.m; sourceTree = "<group>"; };
41
46
  084AEEC72ACF4AB2001A3069 /* FocusedInputObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FocusedInputObserver.swift; sourceTree = "<group>"; };
47
+ 089BA5DB2B3E0C9D000A9A90 /* ViewHierarchyNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewHierarchyNavigator.swift; sourceTree = "<group>"; };
42
48
  134814201AA4EA6300B7C361 /* libKeyboardController.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKeyboardController.a; sourceTree = BUILT_PRODUCTS_DIR; };
43
49
  B3E7B5891CC2AC0600A0062D /* KeyboardControllerViewManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyboardControllerViewManager.mm; sourceTree = "<group>"; };
44
50
  F333F8D128996B1C0015B05F /* KeyboardControllerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyboardControllerView.h; sourceTree = "<group>"; };
@@ -97,6 +103,16 @@
97
103
  path = views;
98
104
  sourceTree = "<group>";
99
105
  };
106
+ 089BA5DD2B3EC978000A9A90 /* traversal */ = {
107
+ isa = PBXGroup;
108
+ children = (
109
+ 089BA5DB2B3E0C9D000A9A90 /* ViewHierarchyNavigator.swift */,
110
+ 0800511B2B65548600928E51 /* FocusedInputHolder.swift */,
111
+ 0800511D2B65558800928E51 /* TextInput.swift */,
112
+ );
113
+ path = traversal;
114
+ sourceTree = "<group>";
115
+ };
100
116
  134814211AA4EA7D00B7C361 /* Products */ = {
101
117
  isa = PBXGroup;
102
118
  children = (
@@ -108,6 +124,7 @@
108
124
  58B511D21A9E6C8500147676 = {
109
125
  isa = PBXGroup;
110
126
  children = (
127
+ 089BA5DD2B3EC978000A9A90 /* traversal */,
111
128
  084AEEC12ACF405C001A3069 /* views */,
112
129
  084AEEC02ACDFC2A001A3069 /* observers */,
113
130
  084AEEBF2ACDFBF1001A3069 /* events */,
@@ -178,13 +195,16 @@
178
195
  files = (
179
196
  084AEEC62ACF49A8001A3069 /* FocusedInputLayoutChangedEvent.m in Sources */,
180
197
  F3626A0728B3FE760021B2D9 /* KeyboardMovementObserver.swift in Sources */,
198
+ 0800511C2B65548600928E51 /* FocusedInputHolder.swift in Sources */,
181
199
  0807071E2A34807B00C05A19 /* Extensions.swift in Sources */,
182
200
  F359D34F28133C26000B6AFE /* KeyboardControllerModule.mm in Sources */,
183
201
  084AEEC82ACF4AB2001A3069 /* FocusedInputObserver.swift in Sources */,
184
202
  F4FF95D7245B92E800C19C63 /* KeyboardControllerViewManager.swift in Sources */,
185
203
  F333F8D428996B8D0015B05F /* KeyboardControllerView.mm in Sources */,
204
+ 0800511E2B65558800928E51 /* TextInput.swift in Sources */,
186
205
  F3F50669289E653B003091D6 /* KeyboardMoveEvent.m in Sources */,
187
206
  083FB9852B15171600C0EFF0 /* TextChangeObserver.swift in Sources */,
207
+ 089BA5DC2B3E0C9D000A9A90 /* ViewHierarchyNavigator.swift in Sources */,
188
208
  083FB9872B15174C00C0EFF0 /* FocusedInputTextChangedEvent.m in Sources */,
189
209
  );
190
210
  runOnlyForDeploymentPostprocessing = 0;
@@ -17,6 +17,12 @@
17
17
 
18
18
  #import "KeyboardControllerModule-Header.h"
19
19
 
20
+ #if __has_include("react_native_keyboard_controller-Swift.h")
21
+ #import "react_native_keyboard_controller-Swift.h"
22
+ #else
23
+ #import <react_native_keyboard_controller/react_native_keyboard_controller-Swift.h>
24
+ #endif
25
+
20
26
  #import <React/RCTEventDispatcherProtocol.h>
21
27
 
22
28
  #ifdef RCT_NEW_ARCH_ENABLED
@@ -75,6 +81,15 @@ RCT_EXPORT_METHOD(dismiss)
75
81
  });
76
82
  }
77
83
 
84
+ #ifdef RCT_NEW_ARCH_ENABLED
85
+ - (void)setFocusTo:(NSString *)direction
86
+ #else
87
+ RCT_EXPORT_METHOD(setFocusTo : (nonnull NSString *)direction)
88
+ #endif
89
+ {
90
+ [ViewHierarchyNavigator setFocusToDirection:direction];
91
+ }
92
+
78
93
  + (KeyboardController *)shared
79
94
  {
80
95
  return shared;
@@ -100,10 +115,13 @@ RCT_EXPORT_METHOD(dismiss)
100
115
  - (NSArray<NSString *> *)supportedEvents
101
116
  {
102
117
  return @[
118
+ // keyboard
103
119
  @"KeyboardController::keyboardWillShow",
104
120
  @"KeyboardController::keyboardDidShow",
105
121
  @"KeyboardController::keyboardWillHide",
106
122
  @"KeyboardController::keyboardDidHide",
123
+ // focused input
124
+ @"KeyboardController::focusDidSet",
107
125
  ];
108
126
  }
109
127
 
@@ -11,6 +11,7 @@
11
11
 
12
12
  @implementation FocusedInputLayoutChangedEvent {
13
13
  NSNumber *_target;
14
+ NSNumber *_parentScrollViewTarget;
14
15
  NSObject *_layout;
15
16
  uint16_t _coalescingKey;
16
17
  }
@@ -29,6 +30,7 @@
29
30
  if ((self = [super init])) {
30
31
  _viewTag = reactTag;
31
32
  _target = [event valueForKey:@"target"];
33
+ _parentScrollViewTarget = [event valueForKey:@"parentScrollViewTarget"];
32
34
  _layout = [event valueForKey:@"layout"];
33
35
  _coalescingKey = 0;
34
36
  }
@@ -46,6 +48,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
46
48
  {
47
49
  NSDictionary *body = @{
48
50
  @"target" : _target,
51
+ @"parentScrollViewTarget" : _parentScrollViewTarget,
49
52
  @"layout" : _layout,
50
53
  };
51
54
 
@@ -11,6 +11,7 @@ import UIKit
11
11
 
12
12
  let noFocusedInputEvent: [String: Any] = [
13
13
  "target": -1,
14
+ "parentScrollViewTarget": -1,
14
15
  "layout": [
15
16
  "absoluteX": 0,
16
17
  "absoluteY": 0,
@@ -26,6 +27,7 @@ public class FocusedInputObserver: NSObject {
26
27
  // class members
27
28
  var onLayoutChangedHandler: (NSDictionary) -> Void
28
29
  var onTextChangedHandler: (String) -> Void
30
+ var onFocusDidSet: (NSDictionary) -> Void
29
31
  // state variables
30
32
  private var isMounted = false
31
33
  // input tracking
@@ -37,10 +39,12 @@ public class FocusedInputObserver: NSObject {
37
39
 
38
40
  @objc public init(
39
41
  onLayoutChangedHandler: @escaping (NSDictionary) -> Void,
40
- onTextChangedHandler: @escaping (String) -> Void
42
+ onTextChangedHandler: @escaping (String) -> Void,
43
+ onFocusDidSet: @escaping (NSDictionary) -> Void
41
44
  ) {
42
45
  self.onLayoutChangedHandler = onLayoutChangedHandler
43
46
  self.onTextChangedHandler = onTextChangedHandler
47
+ self.onFocusDidSet = onFocusDidSet
44
48
  }
45
49
 
46
50
  @objc public func mount() {
@@ -72,9 +76,21 @@ public class FocusedInputObserver: NSObject {
72
76
 
73
77
  @objc func keyboardWillShow(_: Notification) {
74
78
  removeObservers()
75
- currentInput = (UIResponder.current as? UIView)?.superview as UIView?
79
+ let responder = UIResponder.current as? UIView
80
+ currentInput = responder?.superview as UIView?
81
+
76
82
  setupObservers()
77
83
  syncUpLayout()
84
+
85
+ FocusedInputHolder.shared.set(responder as? TextInput)
86
+
87
+ let allInputFields = ViewHierarchyNavigator.getAllInputFields()
88
+ let currentIndex = allInputFields.firstIndex(where: { $0 as? UIView == responder }) ?? -1
89
+
90
+ onFocusDidSet([
91
+ "current": currentIndex,
92
+ "count": allInputFields.count,
93
+ ])
78
94
  }
79
95
 
80
96
  @objc func keyboardWillHide(_: Notification) {
@@ -90,6 +106,7 @@ public class FocusedInputObserver: NSObject {
90
106
 
91
107
  let data: [String: Any] = [
92
108
  "target": responder.reactViewTag,
109
+ "parentScrollViewTarget": responder.parentScrollViewTarget,
93
110
  "layout": [
94
111
  "absoluteX": globalFrame?.origin.x,
95
112
  "absoluteY": globalFrame?.origin.y,
@@ -149,8 +166,7 @@ public class FocusedInputObserver: NSObject {
149
166
  change _: [NSKeyValueChangeKey: Any]?,
150
167
  context _: UnsafeMutableRawPointer?
151
168
  ) {
152
- // swiftlint:disable:next force_cast
153
- if keyPath == "center", object as! NSObject == currentInput! {
169
+ if keyPath == "center", object as? NSObject == currentInput {
154
170
  // we need to read layout in next frame, otherwise we'll get old
155
171
  // layout values
156
172
  DispatchQueue.main.async {
@@ -105,8 +105,7 @@ public class KeyboardMovementObserver: NSObject {
105
105
  change: [NSKeyValueChangeKey: Any]?,
106
106
  context _: UnsafeMutableRawPointer?
107
107
  ) {
108
- // swiftlint:disable:next force_cast
109
- if keyPath == "center", object as! NSObject == _keyboardView! {
108
+ if keyPath == "center", object as? NSObject == _keyboardView {
110
109
  // if we are currently animating keyboard -> we need to ignore values from KVO
111
110
  if displayLink != nil {
112
111
  return
@@ -117,8 +116,10 @@ public class KeyboardMovementObserver: NSObject {
117
116
  return
118
117
  }
119
118
 
120
- // swiftlint:disable:next force_cast
121
- let keyboardFrameY = (change?[.newKey] as! NSValue).cgPointValue.y
119
+ guard let changeValue = change?[.newKey] as? NSValue else {
120
+ return
121
+ }
122
+ let keyboardFrameY = changeValue.cgPointValue.y
122
123
  let keyboardWindowH = keyboardView?.window?.bounds.size.height ?? 0
123
124
  let keyboardPosition = keyboardWindowH - keyboardFrameY
124
125
  let position = CGFloat.interpolate(
@@ -0,0 +1,32 @@
1
+ //
2
+ // FocusedInputHolder.swift
3
+ // KeyboardController
4
+ //
5
+ // Created by Kiryl Ziusko on 27/01/2024.
6
+ // Copyright © 2024 Facebook. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+
11
+ class FocusedInputHolder {
12
+ static let shared = FocusedInputHolder()
13
+
14
+ // Using TextInput protocol as the type for currentFocusedInput
15
+ private weak var currentFocusedInput: TextInput?
16
+
17
+ // Sets the currentFocusedInput to the passed instance conforming to TextInput or clears it if nil is passed
18
+ func set(_ input: TextInput?) {
19
+ currentFocusedInput = input
20
+ }
21
+
22
+ // Requests focus for the currentFocusedInput if it's set
23
+ func requestFocus() {
24
+ currentFocusedInput?.requestFocus()
25
+ }
26
+
27
+ func get() -> TextInput? {
28
+ return currentFocusedInput
29
+ }
30
+
31
+ private init() {}
32
+ }
@@ -0,0 +1,26 @@
1
+ //
2
+ // TextInput.swift
3
+ // KeyboardController
4
+ //
5
+ // Created by Kiryl Ziusko on 27/01/2024.
6
+ // Copyright © 2024 Facebook. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+ import UIKit
11
+
12
+ public protocol TextInput: AnyObject {
13
+ func requestFocus()
14
+ }
15
+
16
+ extension UITextField: TextInput {
17
+ public func requestFocus() {
18
+ becomeFirstResponder()
19
+ }
20
+ }
21
+
22
+ extension UITextView: TextInput {
23
+ public func requestFocus() {
24
+ becomeFirstResponder()
25
+ }
26
+ }
@@ -0,0 +1,116 @@
1
+ //
2
+ // ViewHierarchyNavigator.swift
3
+ // KeyboardController
4
+ //
5
+ // Created by Kiryl Ziusko on 28/12/2023.
6
+ // Copyright © 2023 Facebook. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+ import UIKit
11
+
12
+ @objc(ViewHierarchyNavigator)
13
+ public class ViewHierarchyNavigator: NSObject {
14
+ @objc public static func setFocusTo(direction: String) {
15
+ DispatchQueue.main.async {
16
+ if direction == "current" {
17
+ FocusedInputHolder.shared.requestFocus()
18
+ return
19
+ }
20
+
21
+ let input = (FocusedInputHolder.shared.get() as? UIView) ?? (UIResponder.current as? UIView) ?? nil
22
+ guard let view = input else { return }
23
+
24
+ let textField = findTextInputInDirection(currentFocus: view, direction: direction)
25
+ textField?.requestFocus()
26
+ }
27
+ }
28
+
29
+ public static func getAllInputFields() -> [TextInput] {
30
+ var textInputs = [TextInput]()
31
+
32
+ guard let rootView = UIApplication.shared.keyWindow?.rootViewController?.view else {
33
+ return []
34
+ }
35
+
36
+ // Helper function to recursively search for TextInput views
37
+ func findTextInputs(in view: UIView?) {
38
+ guard let view = view else { return }
39
+
40
+ if let textInput = isValidTextInput(view) {
41
+ textInputs.append(textInput)
42
+ } else {
43
+ for subview in view.subviews {
44
+ findTextInputs(in: subview)
45
+ }
46
+ }
47
+ }
48
+
49
+ findTextInputs(in: rootView)
50
+
51
+ return textInputs
52
+ }
53
+
54
+ private static func findTextInputInDirection(currentFocus: UIView, direction: String) -> TextInput? {
55
+ // Find the parent view group
56
+ guard let parentViewGroup = currentFocus.superview else {
57
+ return nil
58
+ }
59
+
60
+ // Find the index of the current TextInput in its parent
61
+ let currentIndex = parentViewGroup.subviews.firstIndex(of: currentFocus) ?? 0
62
+
63
+ // Define the range for iterating based on the direction
64
+ let range: [Int]
65
+
66
+ if direction == "next" {
67
+ range = Array((currentIndex + 1) ..< parentViewGroup.subviews.count)
68
+ } else {
69
+ range = Array(stride(from: currentIndex - 1, through: 0, by: -1))
70
+ }
71
+
72
+ // Iterate over the range to find the next or previous TextInput
73
+ for i in range {
74
+ let nextChild = parentViewGroup.subviews[i]
75
+
76
+ if let nextTextInput = findTextInputInHierarchy(view: nextChild, direction: direction) {
77
+ return nextTextInput
78
+ }
79
+ }
80
+
81
+ // If no next or previous sibling was found in the parent, recurse to the parent's parent
82
+ return findTextInputInDirection(currentFocus: parentViewGroup, direction: direction)
83
+ }
84
+
85
+ private static func findTextInputInHierarchy(view: UIView, direction: String) -> TextInput? {
86
+ // Check the current view
87
+ if let validTextInput = isValidTextInput(view) {
88
+ return validTextInput
89
+ }
90
+
91
+ // Determine the iteration order based on the direction
92
+ let subviews = direction == "next" ? view.subviews : view.subviews.reversed()
93
+
94
+ // Iterate over subviews
95
+ for subview in subviews {
96
+ if let textField = findTextInputInHierarchy(view: subview, direction: direction) {
97
+ return textField
98
+ }
99
+ }
100
+
101
+ return nil // No valid UITextField or UITextView found
102
+ }
103
+
104
+ // Function to check if the view is a valid text field or text view
105
+ private static func isValidTextInput(_ view: UIView) -> TextInput? {
106
+ if let textField = view as? UITextField, textField.isEnabled {
107
+ return textField
108
+ }
109
+
110
+ if let textView = view as? UITextView, textView.isEditable {
111
+ return textView
112
+ }
113
+
114
+ return nil
115
+ }
116
+ }
@@ -55,6 +55,7 @@ using namespace facebook::react;
55
55
  initOnLayoutChangedHandler:^(NSDictionary *event) {
56
56
  if (self->_eventEmitter) {
57
57
  int target = [event[@"target"] integerValue];
58
+ int parentScrollViewTarget = [event[@"parentScrollViewTarget"] integerValue];
58
59
  double absoluteY = [event[@"layout"][@"absoluteY"] doubleValue];
59
60
  double absoulteX = [event[@"layout"][@"absoluteX"] doubleValue];
60
61
  double y = [event[@"layout"][@"y"] doubleValue];
@@ -68,6 +69,7 @@ using namespace facebook::react;
68
69
  facebook::react::KeyboardControllerViewEventEmitter::
69
70
  OnFocusedInputLayoutChanged{
70
71
  .target = target,
72
+ .parentScrollViewTarget = parentScrollViewTarget,
71
73
  .layout = facebook::react::KeyboardControllerViewEventEmitter::
72
74
  OnFocusedInputLayoutChangedLayout{
73
75
  .absoluteY = absoluteY,
@@ -103,6 +105,9 @@ using namespace facebook::react;
103
105
  [bridge.eventDispatcher sendEvent:textChangedEvent];
104
106
  }
105
107
  }
108
+ }
109
+ onFocusDidSet:^(NSDictionary *data) {
110
+ [KeyboardController.shared sendEvent:@"KeyboardController::focusDidSet" body:data];
106
111
  }];
107
112
  keyboardObserver = [[KeyboardMovementObserver alloc]
108
113
  initWithHandler:^(
@@ -41,7 +41,10 @@ class KeyboardControllerView: UIView {
41
41
  super.init(frame: frame)
42
42
  inputObserver = FocusedInputObserver(
43
43
  onLayoutChangedHandler: { [weak self] event in self?.onLayoutChanged(event: event) },
44
- onTextChangedHandler: { [weak self] text in self?.onTextChanged(text: text) }
44
+ onTextChangedHandler: { [weak self] text in self?.onTextChanged(text: text) },
45
+ onFocusDidSet: { [weak self] event in
46
+ self?.onNotify(event: "KeyboardController::focusDidSet", data: event)
47
+ }
45
48
  )
46
49
  keyboardObserver = KeyboardMovementObserver(
47
50
  handler: { [weak self] event, height, progress, duration, target in
package/jest/index.js CHANGED
@@ -14,6 +14,7 @@ const focusedInput = {
14
14
  input: {
15
15
  value: {
16
16
  target: 1,
17
+ parentScrollViewTarget: -1,
17
18
  layout: {
18
19
  x: 0,
19
20
  y: 0,
@@ -34,6 +35,7 @@ const mock = {
34
35
  useResizeMode: jest.fn(),
35
36
  useGenericKeyboardHandler: jest.fn(),
36
37
  useKeyboardHandler: jest.fn(),
38
+ useKeyboardContext: jest.fn().mockReturnValue(values),
37
39
  /// input
38
40
  useReanimatedFocusedInput: jest.fn().mockReturnValue(focusedInput),
39
41
  useFocusedInputHandler: jest.fn(),
@@ -46,6 +48,23 @@ const mock = {
46
48
  setInputMode: jest.fn(),
47
49
  setDefaultMode: jest.fn(),
48
50
  dismiss: jest.fn(),
51
+ setFocusTo: jest.fn(),
52
+ },
53
+ AndroidSoftInputModes: {
54
+ SOFT_INPUT_ADJUST_NOTHING: 48,
55
+ SOFT_INPUT_ADJUST_PAN: 32,
56
+ SOFT_INPUT_ADJUST_RESIZE: 16,
57
+ SOFT_INPUT_ADJUST_UNSPECIFIED: 0,
58
+ SOFT_INPUT_IS_FORWARD_NAVIGATION: 256,
59
+ SOFT_INPUT_MASK_ADJUST: 240,
60
+ SOFT_INPUT_MASK_STATE: 15,
61
+ SOFT_INPUT_MODE_CHANGED: 512,
62
+ SOFT_INPUT_STATE_ALWAYS_HIDDEN: 3,
63
+ SOFT_INPUT_STATE_ALWAYS_VISIBLE: 5,
64
+ SOFT_INPUT_STATE_HIDDEN: 2,
65
+ SOFT_INPUT_STATE_UNCHANGED: 1,
66
+ SOFT_INPUT_STATE_UNSPECIFIED: 0,
67
+ SOFT_INPUT_STATE_VISIBLE: 4,
49
68
  },
50
69
  KeyboardEvents: {
51
70
  addListener: jest.fn(() => ({ remove: jest.fn() })),
@@ -59,6 +78,7 @@ const mock = {
59
78
  KeyboardStickyView: View,
60
79
  KeyboardAvoidingView: View,
61
80
  KeyboardAwareScrollView: ScrollView,
81
+ KeyboardToolbar: View,
62
82
  };
63
83
 
64
84
  module.exports = mock;
@@ -3,13 +3,14 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.KeyboardGestureArea = exports.KeyboardEvents = exports.KeyboardControllerView = exports.KeyboardController = void 0;
6
+ exports.KeyboardGestureArea = exports.KeyboardEvents = exports.KeyboardControllerView = exports.KeyboardController = exports.FocusedInputEvents = void 0;
7
7
  var _reactNative = require("react-native");
8
8
  const NOOP = () => {};
9
9
  const KeyboardController = {
10
10
  setDefaultMode: NOOP,
11
11
  setInputMode: NOOP,
12
12
  dismiss: NOOP,
13
+ setFocusTo: NOOP,
13
14
  addListener: NOOP,
14
15
  removeListeners: NOOP
15
16
  };
@@ -19,7 +20,17 @@ const KeyboardEvents = {
19
20
  remove: NOOP
20
21
  })
21
22
  };
23
+ /**
24
+ * This API is not documented, it's for internal usage only (for now), and is a subject to potential breaking changes in future.
25
+ * Use it with cautious.
26
+ */
22
27
  exports.KeyboardEvents = KeyboardEvents;
28
+ const FocusedInputEvents = {
29
+ addListener: () => ({
30
+ remove: NOOP
31
+ })
32
+ };
33
+ exports.FocusedInputEvents = FocusedInputEvents;
23
34
  const KeyboardControllerView = _reactNative.View;
24
35
  exports.KeyboardControllerView = KeyboardControllerView;
25
36
  const KeyboardGestureArea = _reactNative.View;
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","NOOP","KeyboardController","setDefaultMode","setInputMode","dismiss","addListener","removeListeners","exports","KeyboardEvents","remove","KeyboardControllerView","View","KeyboardGestureArea"],"sources":["bindings.ts"],"sourcesContent":["import { View } from \"react-native\";\n\nimport type {\n KeyboardControllerModule,\n KeyboardControllerProps,\n KeyboardEventsModule,\n KeyboardGestureAreaProps,\n} from \"./types\";\nimport type { EmitterSubscription } from \"react-native\";\n\nconst NOOP = () => {};\nexport const KeyboardController: KeyboardControllerModule = {\n setDefaultMode: NOOP,\n setInputMode: NOOP,\n dismiss: NOOP,\n addListener: NOOP,\n removeListeners: NOOP,\n};\nexport const KeyboardEvents: KeyboardEventsModule = {\n addListener: () => ({ remove: NOOP } as EmitterSubscription),\n};\nexport const KeyboardControllerView =\n View as unknown as React.FC<KeyboardControllerProps>;\nexport const KeyboardGestureArea =\n View as unknown as React.FC<KeyboardGestureAreaProps>;\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAUA,MAAMC,IAAI,GAAGA,CAAA,KAAM,CAAC,CAAC;AACd,MAAMC,kBAA4C,GAAG;EAC1DC,cAAc,EAAEF,IAAI;EACpBG,YAAY,EAAEH,IAAI;EAClBI,OAAO,EAAEJ,IAAI;EACbK,WAAW,EAAEL,IAAI;EACjBM,eAAe,EAAEN;AACnB,CAAC;AAACO,OAAA,CAAAN,kBAAA,GAAAA,kBAAA;AACK,MAAMO,cAAoC,GAAG;EAClDH,WAAW,EAAEA,CAAA,MAAO;IAAEI,MAAM,EAAET;EAAK,CAAC;AACtC,CAAC;AAACO,OAAA,CAAAC,cAAA,GAAAA,cAAA;AACK,MAAME,sBAAsB,GACjCC,iBAAoD;AAACJ,OAAA,CAAAG,sBAAA,GAAAA,sBAAA;AAChD,MAAME,mBAAmB,GAC9BD,iBAAqD;AAACJ,OAAA,CAAAK,mBAAA,GAAAA,mBAAA"}
1
+ {"version":3,"names":["_reactNative","require","NOOP","KeyboardController","setDefaultMode","setInputMode","dismiss","setFocusTo","addListener","removeListeners","exports","KeyboardEvents","remove","FocusedInputEvents","KeyboardControllerView","View","KeyboardGestureArea"],"sources":["bindings.ts"],"sourcesContent":["import { View } from \"react-native\";\n\nimport type {\n FocusedInputEventsModule,\n KeyboardControllerModule,\n KeyboardControllerProps,\n KeyboardEventsModule,\n KeyboardGestureAreaProps,\n} from \"./types\";\nimport type { EmitterSubscription } from \"react-native\";\n\nconst NOOP = () => {};\nexport const KeyboardController: KeyboardControllerModule = {\n setDefaultMode: NOOP,\n setInputMode: NOOP,\n dismiss: NOOP,\n setFocusTo: NOOP,\n addListener: NOOP,\n removeListeners: NOOP,\n};\nexport const KeyboardEvents: KeyboardEventsModule = {\n addListener: () => ({ remove: NOOP } as EmitterSubscription),\n};\n/**\n * This API is not documented, it's for internal usage only (for now), and is a subject to potential breaking changes in future.\n * Use it with cautious.\n */\nexport const FocusedInputEvents: FocusedInputEventsModule = {\n addListener: () => ({ remove: NOOP } as EmitterSubscription),\n};\nexport const KeyboardControllerView =\n View as unknown as React.FC<KeyboardControllerProps>;\nexport const KeyboardGestureArea =\n View as unknown as React.FC<KeyboardGestureAreaProps>;\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAWA,MAAMC,IAAI,GAAGA,CAAA,KAAM,CAAC,CAAC;AACd,MAAMC,kBAA4C,GAAG;EAC1DC,cAAc,EAAEF,IAAI;EACpBG,YAAY,EAAEH,IAAI;EAClBI,OAAO,EAAEJ,IAAI;EACbK,UAAU,EAAEL,IAAI;EAChBM,WAAW,EAAEN,IAAI;EACjBO,eAAe,EAAEP;AACnB,CAAC;AAACQ,OAAA,CAAAP,kBAAA,GAAAA,kBAAA;AACK,MAAMQ,cAAoC,GAAG;EAClDH,WAAW,EAAEA,CAAA,MAAO;IAAEI,MAAM,EAAEV;EAAK,CAAC;AACtC,CAAC;AACD;AACA;AACA;AACA;AAHAQ,OAAA,CAAAC,cAAA,GAAAA,cAAA;AAIO,MAAME,kBAA4C,GAAG;EAC1DL,WAAW,EAAEA,CAAA,MAAO;IAAEI,MAAM,EAAEV;EAAK,CAAC;AACtC,CAAC;AAACQ,OAAA,CAAAG,kBAAA,GAAAA,kBAAA;AACK,MAAMC,sBAAsB,GACjCC,iBAAoD;AAACL,OAAA,CAAAI,sBAAA,GAAAA,sBAAA;AAChD,MAAME,mBAAmB,GAC9BD,iBAAqD;AAACL,OAAA,CAAAM,mBAAA,GAAAA,mBAAA"}
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.KeyboardGestureArea = exports.KeyboardEvents = exports.KeyboardControllerView = exports.KeyboardController = void 0;
6
+ exports.KeyboardGestureArea = exports.KeyboardEvents = exports.KeyboardControllerView = exports.KeyboardController = exports.FocusedInputEvents = void 0;
7
7
  var _reactNative = require("react-native");
8
8
  const LINKING_ERROR = `The package 'react-native-keyboard-controller' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
9
9
  ios: "- You have run 'pod install'\n",
@@ -16,11 +16,20 @@ const KeyboardController = RCTKeyboardController ? RCTKeyboardController : new P
16
16
  }
17
17
  });
18
18
  exports.KeyboardController = KeyboardController;
19
+ const KEYBOARD_CONTROLLER_NAMESPACE = "KeyboardController::";
19
20
  const eventEmitter = new _reactNative.NativeEventEmitter(KeyboardController);
20
21
  const KeyboardEvents = {
21
- addListener: (name, cb) => eventEmitter.addListener("KeyboardController::" + name, cb)
22
+ addListener: (name, cb) => eventEmitter.addListener(KEYBOARD_CONTROLLER_NAMESPACE + name, cb)
22
23
  };
24
+ /**
25
+ * This API is not documented, it's for internal usage only (for now), and is a subject to potential breaking changes in future.
26
+ * Use it with cautious.
27
+ */
23
28
  exports.KeyboardEvents = KeyboardEvents;
29
+ const FocusedInputEvents = {
30
+ addListener: (name, cb) => eventEmitter.addListener(KEYBOARD_CONTROLLER_NAMESPACE + name, cb)
31
+ };
32
+ exports.FocusedInputEvents = FocusedInputEvents;
24
33
  const KeyboardControllerView = require("./specs/KeyboardControllerViewNativeComponent").default;
25
34
  exports.KeyboardControllerView = KeyboardControllerView;
26
35
  const KeyboardGestureArea = _reactNative.Platform.OS === "android" && _reactNative.Platform.Version >= 30 ? require("./specs/KeyboardGestureAreaNativeComponent").default : _ref => {
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","RCTKeyboardController","KeyboardController","Proxy","get","Error","exports","eventEmitter","NativeEventEmitter","KeyboardEvents","addListener","name","cb","KeyboardControllerView","KeyboardGestureArea","OS","Version","_ref","children"],"sources":["bindings.native.ts"],"sourcesContent":["import { NativeEventEmitter, Platform } from \"react-native\";\n\nimport type {\n KeyboardControllerModule,\n KeyboardControllerProps,\n KeyboardEventsModule,\n KeyboardGestureAreaProps,\n} from \"./types\";\n\nconst LINKING_ERROR =\n `The package 'react-native-keyboard-controller' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: \"\" }) +\n \"- You rebuilt the app after installing the package\\n\" +\n \"- You are not using Expo Go\\n\";\n\nconst RCTKeyboardController =\n require(\"./specs/NativeKeyboardController\").default;\nexport const KeyboardController = (\n RCTKeyboardController\n ? RCTKeyboardController\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n },\n )\n) as KeyboardControllerModule;\n\nconst eventEmitter = new NativeEventEmitter(KeyboardController);\n\nexport const KeyboardEvents: KeyboardEventsModule = {\n addListener: (name, cb) =>\n eventEmitter.addListener(\"KeyboardController::\" + name, cb),\n};\nexport const KeyboardControllerView: React.FC<KeyboardControllerProps> =\n require(\"./specs/KeyboardControllerViewNativeComponent\").default;\nexport const KeyboardGestureArea: React.FC<KeyboardGestureAreaProps> =\n Platform.OS === \"android\" && Platform.Version >= 30\n ? require(\"./specs/KeyboardGestureAreaNativeComponent\").default\n : ({ children }: KeyboardGestureAreaProps) => children;\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AASA,MAAMC,aAAa,GAChB,2FAA0F,GAC3FC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,qBAAqB,GACzBN,OAAO,CAAC,kCAAkC,CAAC,CAACK,OAAO;AAC9C,MAAME,kBAAkB,GAC7BD,qBAAqB,GACjBA,qBAAqB,GACrB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACT,aAAa,CAAC;EAChC;AACF,CACF,CACuB;AAACU,OAAA,CAAAJ,kBAAA,GAAAA,kBAAA;AAE9B,MAAMK,YAAY,GAAG,IAAIC,+BAAkB,CAACN,kBAAkB,CAAC;AAExD,MAAMO,cAAoC,GAAG;EAClDC,WAAW,EAAEA,CAACC,IAAI,EAAEC,EAAE,KACpBL,YAAY,CAACG,WAAW,CAAC,sBAAsB,GAAGC,IAAI,EAAEC,EAAE;AAC9D,CAAC;AAACN,OAAA,CAAAG,cAAA,GAAAA,cAAA;AACK,MAAMI,sBAAyD,GACpElB,OAAO,CAAC,+CAA+C,CAAC,CAACK,OAAO;AAACM,OAAA,CAAAO,sBAAA,GAAAA,sBAAA;AAC5D,MAAMC,mBAAuD,GAClEjB,qBAAQ,CAACkB,EAAE,KAAK,SAAS,IAAIlB,qBAAQ,CAACmB,OAAO,IAAI,EAAE,GAC/CrB,OAAO,CAAC,4CAA4C,CAAC,CAACK,OAAO,GAC7DiB,IAAA;EAAA,IAAC;IAAEC;EAAmC,CAAC,GAAAD,IAAA;EAAA,OAAKC,QAAQ;AAAA;AAACZ,OAAA,CAAAQ,mBAAA,GAAAA,mBAAA"}
1
+ {"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","RCTKeyboardController","KeyboardController","Proxy","get","Error","exports","KEYBOARD_CONTROLLER_NAMESPACE","eventEmitter","NativeEventEmitter","KeyboardEvents","addListener","name","cb","FocusedInputEvents","KeyboardControllerView","KeyboardGestureArea","OS","Version","_ref","children"],"sources":["bindings.native.ts"],"sourcesContent":["import { NativeEventEmitter, Platform } from \"react-native\";\n\nimport type {\n FocusedInputEventsModule,\n KeyboardControllerModule,\n KeyboardControllerProps,\n KeyboardEventsModule,\n KeyboardGestureAreaProps,\n} from \"./types\";\n\nconst LINKING_ERROR =\n `The package 'react-native-keyboard-controller' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: \"\" }) +\n \"- You rebuilt the app after installing the package\\n\" +\n \"- You are not using Expo Go\\n\";\n\nconst RCTKeyboardController =\n require(\"./specs/NativeKeyboardController\").default;\nexport const KeyboardController = (\n RCTKeyboardController\n ? RCTKeyboardController\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n },\n )\n) as KeyboardControllerModule;\n\nconst KEYBOARD_CONTROLLER_NAMESPACE = \"KeyboardController::\";\nconst eventEmitter = new NativeEventEmitter(KeyboardController);\n\nexport const KeyboardEvents: KeyboardEventsModule = {\n addListener: (name, cb) =>\n eventEmitter.addListener(KEYBOARD_CONTROLLER_NAMESPACE + name, cb),\n};\n/**\n * This API is not documented, it's for internal usage only (for now), and is a subject to potential breaking changes in future.\n * Use it with cautious.\n */\nexport const FocusedInputEvents: FocusedInputEventsModule = {\n addListener: (name, cb) =>\n eventEmitter.addListener(KEYBOARD_CONTROLLER_NAMESPACE + name, cb),\n};\nexport const KeyboardControllerView: React.FC<KeyboardControllerProps> =\n require(\"./specs/KeyboardControllerViewNativeComponent\").default;\nexport const KeyboardGestureArea: React.FC<KeyboardGestureAreaProps> =\n Platform.OS === \"android\" && Platform.Version >= 30\n ? require(\"./specs/KeyboardGestureAreaNativeComponent\").default\n : ({ children }: KeyboardGestureAreaProps) => children;\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAUA,MAAMC,aAAa,GAChB,2FAA0F,GAC3FC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,qBAAqB,GACzBN,OAAO,CAAC,kCAAkC,CAAC,CAACK,OAAO;AAC9C,MAAME,kBAAkB,GAC7BD,qBAAqB,GACjBA,qBAAqB,GACrB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACT,aAAa,CAAC;EAChC;AACF,CACF,CACuB;AAACU,OAAA,CAAAJ,kBAAA,GAAAA,kBAAA;AAE9B,MAAMK,6BAA6B,GAAG,sBAAsB;AAC5D,MAAMC,YAAY,GAAG,IAAIC,+BAAkB,CAACP,kBAAkB,CAAC;AAExD,MAAMQ,cAAoC,GAAG;EAClDC,WAAW,EAAEA,CAACC,IAAI,EAAEC,EAAE,KACpBL,YAAY,CAACG,WAAW,CAACJ,6BAA6B,GAAGK,IAAI,EAAEC,EAAE;AACrE,CAAC;AACD;AACA;AACA;AACA;AAHAP,OAAA,CAAAI,cAAA,GAAAA,cAAA;AAIO,MAAMI,kBAA4C,GAAG;EAC1DH,WAAW,EAAEA,CAACC,IAAI,EAAEC,EAAE,KACpBL,YAAY,CAACG,WAAW,CAACJ,6BAA6B,GAAGK,IAAI,EAAEC,EAAE;AACrE,CAAC;AAACP,OAAA,CAAAQ,kBAAA,GAAAA,kBAAA;AACK,MAAMC,sBAAyD,GACpEpB,OAAO,CAAC,+CAA+C,CAAC,CAACK,OAAO;AAACM,OAAA,CAAAS,sBAAA,GAAAA,sBAAA;AAC5D,MAAMC,mBAAuD,GAClEnB,qBAAQ,CAACoB,EAAE,KAAK,SAAS,IAAIpB,qBAAQ,CAACqB,OAAO,IAAI,EAAE,GAC/CvB,OAAO,CAAC,4CAA4C,CAAC,CAACK,OAAO,GAC7DmB,IAAA;EAAA,IAAC;IAAEC;EAAmC,CAAC,GAAAD,IAAA;EAAA,OAAKC,QAAQ;AAAA;AAACd,OAAA,CAAAU,mBAAA,GAAAA,mBAAA"}