react-native-keyboard-controller 1.11.7 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputSelectionChangedEvent.kt +51 -0
  2. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/EditText.kt +79 -0
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +1 -2
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/View.kt +1 -1
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/interactive/interpolators/IosInterpolator.kt +1 -1
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +32 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +1 -1
  8. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +2 -0
  9. package/android/src/main/java/com/reactnativekeyboardcontroller/ui/FrameScheduler.kt +40 -0
  10. package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +1 -1
  11. package/ios/KeyboardController-Bridging-Header.h +1 -0
  12. package/ios/core/KeyboardAnimation.swift +77 -0
  13. package/ios/core/SpringAnimation.swift +60 -0
  14. package/ios/core/UIUtils.swift +11 -0
  15. package/ios/delegates/KCTextInputCompositeDelegate.swift +148 -0
  16. package/ios/events/FocusedInputSelectionChangedEvent.h +15 -0
  17. package/ios/events/FocusedInputSelectionChangedEvent.m +76 -0
  18. package/ios/objc/RCTUITextView+DelegateManager.h +14 -0
  19. package/ios/objc/RCTUITextView+DelegateManager.m +26 -0
  20. package/ios/observers/FocusedInputObserver.swift +74 -13
  21. package/ios/observers/KeyboardMovementObserver.swift +39 -2
  22. package/ios/views/KeyboardControllerView.mm +45 -8
  23. package/ios/views/KeyboardControllerViewManager.mm +1 -0
  24. package/ios/views/KeyboardControllerViewManager.swift +10 -2
  25. package/lib/commonjs/animated.js +8 -0
  26. package/lib/commonjs/animated.js.map +1 -1
  27. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
  28. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +1 -1
  29. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
  30. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
  31. package/lib/commonjs/components/KeyboardToolbar/index.js +25 -7
  32. package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
  33. package/lib/commonjs/components/KeyboardToolbar/types.js.map +1 -1
  34. package/lib/commonjs/components/index.js.map +1 -1
  35. package/lib/commonjs/index.js.map +1 -1
  36. package/lib/commonjs/reanimated.js +2 -1
  37. package/lib/commonjs/reanimated.js.map +1 -1
  38. package/lib/commonjs/reanimated.native.js +18 -1
  39. package/lib/commonjs/reanimated.native.js.map +1 -1
  40. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  41. package/lib/commonjs/types.js.map +1 -1
  42. package/lib/module/animated.js +9 -1
  43. package/lib/module/animated.js.map +1 -1
  44. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
  45. package/lib/module/components/KeyboardAwareScrollView/index.js +1 -1
  46. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
  47. package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
  48. package/lib/module/components/KeyboardToolbar/index.js +26 -8
  49. package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
  50. package/lib/module/components/KeyboardToolbar/types.js.map +1 -1
  51. package/lib/module/components/index.js.map +1 -1
  52. package/lib/module/index.js.map +1 -1
  53. package/lib/module/reanimated.js +1 -0
  54. package/lib/module/reanimated.js.map +1 -1
  55. package/lib/module/reanimated.native.js +16 -0
  56. package/lib/module/reanimated.native.js.map +1 -1
  57. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  58. package/lib/module/types.js.map +1 -1
  59. package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +20 -0
  60. package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +8 -0
  61. package/lib/typescript/components/KeyboardStickyView/index.d.ts +15 -0
  62. package/lib/typescript/components/KeyboardToolbar/index.d.ts +21 -1
  63. package/lib/typescript/components/KeyboardToolbar/types.d.ts +3 -1
  64. package/lib/typescript/components/index.d.ts +3 -0
  65. package/lib/typescript/index.d.ts +1 -1
  66. package/lib/typescript/reanimated.d.ts +2 -1
  67. package/lib/typescript/reanimated.native.d.ts +7 -4
  68. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +16 -0
  69. package/lib/typescript/types.d.ts +21 -0
  70. package/package.json +4 -3
  71. package/src/animated.tsx +12 -0
  72. package/src/components/KeyboardAvoidingView/index.tsx +5 -2
  73. package/src/components/KeyboardAwareScrollView/index.tsx +2 -2
  74. package/src/components/KeyboardStickyView/index.tsx +1 -1
  75. package/src/components/KeyboardToolbar/index.tsx +47 -7
  76. package/src/components/KeyboardToolbar/types.ts +25 -1
  77. package/src/components/index.ts +3 -0
  78. package/src/index.ts +6 -1
  79. package/src/reanimated.native.ts +30 -3
  80. package/src/reanimated.ts +6 -0
  81. package/src/specs/KeyboardControllerViewNativeComponent.ts +17 -0
  82. package/src/types.ts +31 -0
  83. package/ios/observers/TextChangeObserver.swift +0 -41
@@ -0,0 +1,76 @@
1
+ //
2
+ // FocusedInputSelectionChangedEvent.m
3
+ // KeyboardController
4
+ //
5
+ // Created by Kiryl Ziusko on 23/04/2024.
6
+ //
7
+
8
+ #import "FocusedInputSelectionChangedEvent.h"
9
+ #import <React/RCTAssert.h>
10
+
11
+ @implementation FocusedInputSelectionChangedEvent {
12
+ NSNumber *_target;
13
+ NSObject *_selection;
14
+ uint16_t _coalescingKey;
15
+ }
16
+
17
+ - (NSString *)eventName
18
+ {
19
+ return @"onFocusedInputSelectionChanged";
20
+ }
21
+
22
+ @synthesize viewTag = _viewTag;
23
+
24
+ - (instancetype)initWithReactTag:(NSNumber *)reactTag event:(NSObject *)event
25
+ {
26
+ RCTAssertParam(reactTag);
27
+
28
+ if ((self = [super init])) {
29
+ _viewTag = reactTag;
30
+
31
+ _selection = [event valueForKey:@"selection"];
32
+ _target = [event valueForKey:@"target"];
33
+ _coalescingKey = 0;
34
+ }
35
+ return self;
36
+ }
37
+
38
+ RCT_NOT_IMPLEMENTED(-(instancetype)init)
39
+
40
+ - (uint16_t)coalescingKey
41
+ {
42
+ return _coalescingKey;
43
+ }
44
+
45
+ - (NSDictionary *)body
46
+ {
47
+ NSDictionary *body = @{
48
+ @"selection" : _selection,
49
+ @"target" : _target,
50
+ };
51
+
52
+ return body;
53
+ }
54
+
55
+ - (BOOL)canCoalesce
56
+ {
57
+ return NO;
58
+ }
59
+
60
+ - (FocusedInputSelectionChangedEvent *)coalesceWithEvent:
61
+ (FocusedInputSelectionChangedEvent *)newEvent
62
+ {
63
+ return newEvent;
64
+ }
65
+
66
+ + (NSString *)moduleDotMethod
67
+ {
68
+ return @"RCTEventEmitter.receiveEvent";
69
+ }
70
+
71
+ - (NSArray *)arguments
72
+ {
73
+ return @[ self.viewTag, RCTNormalizeInputEventName(self.eventName), [self body] ];
74
+ }
75
+
76
+ @end
@@ -0,0 +1,14 @@
1
+ //
2
+ // RCTTextView+DelegateManager.h
3
+ // react-native-keyboard-controller
4
+ //
5
+ // Created by Kiryl Ziusko on 24/04/2024.
6
+ //
7
+
8
+ #import <React/RCTUITextView.h>
9
+
10
+ @interface RCTUITextView (DelegateManager)
11
+
12
+ - (void)setForceDelegate:(id<UITextViewDelegate>)delegate;
13
+
14
+ @end
@@ -0,0 +1,26 @@
1
+ //
2
+ // RCTUITextView+DelegateManager.m
3
+ // react-native-keyboard-controller
4
+ //
5
+ // Created by Kiryl Ziusko on 24/04/2024.
6
+ //
7
+
8
+ #import <objc/runtime.h>
9
+ #import "RCTUITextView+DelegateManager.h"
10
+
11
+ @implementation RCTUITextView (DelegateManager)
12
+
13
+ /**
14
+ * We are aware that delegate is set by RN on mount and we can not re-define it
15
+ * but we are using composite delegate to forward all calls to original delegate
16
+ * so we use this method to force set our delegate
17
+ */
18
+ - (void)setForceDelegate:(id<UITextViewDelegate>)delegate
19
+ {
20
+ Ivar ivar = class_getInstanceVariable([UITextView class], "_delegate");
21
+ if (ivar) {
22
+ object_setIvar(self, ivar, delegate);
23
+ }
24
+ }
25
+
26
+ @end
@@ -25,26 +25,46 @@ let noFocusedInputEvent: [String: Any] = [
25
25
  @objc(FocusedInputObserver)
26
26
  public class FocusedInputObserver: NSObject {
27
27
  // class members
28
+ /// handlers
28
29
  var onLayoutChangedHandler: (NSDictionary) -> Void
29
30
  var onTextChangedHandler: (String) -> Void
31
+ var onSelectionChangedHandler: (NSDictionary) -> Void
30
32
  var onFocusDidSet: (NSDictionary) -> Void
33
+ /// delegates
34
+ var delegate: KCTextInputCompositeDelegate
31
35
  // state variables
32
36
  private var isMounted = false
33
37
  // input tracking
34
38
  private var currentInput: UIView?
39
+ private var currentResponder: UIView?
35
40
  private var hasObservers = false
36
41
  private var lastEventDispatched: [AnyHashable: Any] = noFocusedInputEvent
37
- // observers
38
- private let textChangeObserver = TextChangeObserver()
39
42
 
40
43
  @objc public init(
41
44
  onLayoutChangedHandler: @escaping (NSDictionary) -> Void,
42
45
  onTextChangedHandler: @escaping (String) -> Void,
46
+ onSelectionChangedHandler: @escaping (NSDictionary) -> Void,
43
47
  onFocusDidSet: @escaping (NSDictionary) -> Void
44
48
  ) {
45
49
  self.onLayoutChangedHandler = onLayoutChangedHandler
46
50
  self.onTextChangedHandler = onTextChangedHandler
51
+ self.onSelectionChangedHandler = onSelectionChangedHandler
47
52
  self.onFocusDidSet = onFocusDidSet
53
+
54
+ // Temporary initialization of the delegate with an empty closure
55
+ delegate = KCTextInputCompositeDelegate(onSelectionChange: { _ in }, onTextChange: { _ in })
56
+
57
+ super.init()
58
+
59
+ // Initialize the delegate
60
+ delegate = KCTextInputCompositeDelegate(
61
+ onSelectionChange: { [weak self] event in
62
+ self?.onSelectionChange(event)
63
+ },
64
+ onTextChange: { [weak self] text in
65
+ self?.onTextChanged(text: text)
66
+ }
67
+ )
48
68
  }
49
69
 
50
70
  @objc public func mount() {
@@ -75,17 +95,18 @@ public class FocusedInputObserver: NSObject {
75
95
  }
76
96
 
77
97
  @objc func keyboardWillShow(_: Notification) {
78
- removeObservers()
79
98
  let responder = UIResponder.current as? UIView
80
- currentInput = responder?.superview as UIView?
99
+ removeObservers(newResponder: responder)
100
+ currentResponder = responder
101
+ currentInput = currentResponder?.superview as UIView?
81
102
 
82
103
  setupObservers()
83
104
  syncUpLayout()
84
105
 
85
- FocusedInputHolder.shared.set(responder as? TextInput)
106
+ FocusedInputHolder.shared.set(currentResponder as? TextInput)
86
107
 
87
108
  let allInputFields = ViewHierarchyNavigator.getAllInputFields()
88
- let currentIndex = allInputFields.firstIndex(where: { $0 as? UIView == responder }) ?? -1
109
+ let currentIndex = allInputFields.firstIndex(where: { $0 as? UIView == currentResponder }) ?? -1
89
110
 
90
111
  onFocusDidSet([
91
112
  "current": currentIndex,
@@ -94,14 +115,15 @@ public class FocusedInputObserver: NSObject {
94
115
  }
95
116
 
96
117
  @objc func keyboardWillHide(_: Notification) {
97
- removeObservers()
118
+ removeObservers(newResponder: nil)
98
119
  currentInput = nil
120
+ currentResponder = nil
99
121
  dispatchEventToJS(data: noFocusedInputEvent)
100
122
  }
101
123
 
102
124
  @objc func syncUpLayout() {
103
- let responder = UIResponder.current
104
- let focusedInput = (responder as? UIView)?.superview
125
+ let responder = currentResponder as UIResponder?
126
+ let focusedInput = currentInput
105
127
  let globalFrame = focusedInput?.globalFrame
106
128
 
107
129
  let data: [String: Any] = [
@@ -145,18 +167,42 @@ public class FocusedInputObserver: NSObject {
145
167
  if currentInput != nil {
146
168
  hasObservers = true
147
169
  currentInput?.addObserver(self, forKeyPath: "center", options: .new, context: nil)
148
- textChangeObserver.observeTextChanges(for: UIResponder.current, handler: onTextChanged)
170
+
171
+ substituteDelegate(currentResponder)
149
172
  }
150
173
  }
151
174
 
152
- private func removeObservers() {
153
- if !hasObservers {
175
+ private func removeObservers(newResponder: UIResponder?) {
176
+ if newResponder == currentResponder || !hasObservers {
154
177
  return
155
178
  }
156
179
 
157
180
  hasObservers = false
158
181
  currentInput?.removeObserver(self, forKeyPath: "center", context: nil)
159
- textChangeObserver.removeObserver()
182
+
183
+ substituteDelegateBack(currentResponder)
184
+ }
185
+
186
+ private func substituteDelegate(_ input: UIResponder?) {
187
+ if let textField = input as? UITextField {
188
+ if !(textField.delegate is KCTextInputCompositeDelegate) {
189
+ delegate.setTextFieldDelegate(delegate: textField.delegate)
190
+ textField.delegate = delegate
191
+ }
192
+ } else if let textView = input as? UITextView {
193
+ if !(textView.delegate is KCTextInputCompositeDelegate) {
194
+ delegate.setTextViewDelegate(delegate: textView.delegate)
195
+ (textView as? RCTUITextView)?.setForceDelegate(delegate)
196
+ }
197
+ }
198
+ }
199
+
200
+ private func substituteDelegateBack(_ input: UIResponder?) {
201
+ if let textField = input as? UITextField {
202
+ textField.delegate = delegate.activeDelegate as? UITextFieldDelegate
203
+ } else if let textView = input as? UITextView {
204
+ (textView as? RCTUITextView)?.setForceDelegate(delegate.activeDelegate as? UITextViewDelegate)
205
+ }
160
206
  }
161
207
 
162
208
  // swiftlint:disable:next block_based_kvo
@@ -174,4 +220,19 @@ public class FocusedInputObserver: NSObject {
174
220
  }
175
221
  }
176
222
  }
223
+
224
+ private func onSelectionChange(_ event: NSDictionary) {
225
+ // Safely retrieve the event dictionary as a Swift dictionary
226
+ guard let eventDict = event as? [String: Any] else {
227
+ return
228
+ }
229
+
230
+ let target: [String: Any] = [
231
+ "target": (currentResponder as UIResponder?).reactViewTag,
232
+ ]
233
+
234
+ let data = target.merging(eventDict) { _, new in new }
235
+
236
+ onSelectionChangedHandler(data as NSDictionary)
237
+ }
177
238
  }
@@ -39,6 +39,7 @@ public class KeyboardMovementObserver: NSObject {
39
39
  private var keyboardHeight: CGFloat = 0.0
40
40
  private var duration = 0
41
41
  private var tag: NSNumber = -1
42
+ private var animation: KeyboardAnimation?
42
43
 
43
44
  @objc public init(
44
45
  handler: @escaping (NSString, NSNumber, NSNumber, NSNumber, NSNumber) -> Void,
@@ -179,6 +180,7 @@ public class KeyboardMovementObserver: NSObject {
179
180
  onNotify("KeyboardController::keyboardWillShow", data)
180
181
 
181
182
  setupKeyboardWatcher()
183
+ initializeAnimation(fromValue: prevKeyboardPosition, toValue: keyboardHeight)
182
184
  }
183
185
  }
184
186
 
@@ -201,6 +203,7 @@ public class KeyboardMovementObserver: NSObject {
201
203
 
202
204
  setupKeyboardWatcher()
203
205
  removeKVObserver()
206
+ initializeAnimation(fromValue: prevKeyboardPosition, toValue: 0)
204
207
  }
205
208
 
206
209
  @objc func keyboardDidAppear(_ notification: Notification) {
@@ -224,6 +227,7 @@ public class KeyboardMovementObserver: NSObject {
224
227
 
225
228
  removeKeyboardWatcher()
226
229
  setupKVObserver()
230
+ animation = nil
227
231
  }
228
232
  }
229
233
 
@@ -243,6 +247,7 @@ public class KeyboardMovementObserver: NSObject {
243
247
  onNotify("KeyboardController::keyboardDidHide", data)
244
248
 
245
249
  removeKeyboardWatcher()
250
+ animation = nil
246
251
  }
247
252
 
248
253
  @objc func setupKeyboardWatcher() {
@@ -263,20 +268,52 @@ public class KeyboardMovementObserver: NSObject {
263
268
  displayLink = nil
264
269
  }
265
270
 
266
- @objc func updateKeyboardFrame() {
271
+ func initializeAnimation(fromValue: Double, toValue: Double) {
272
+ let positionAnimation = keyboardView?.layer.presentation()?.animation(forKey: "position") as? CASpringAnimation
273
+ guard let keyboardAnimation = positionAnimation else {
274
+ return
275
+ }
276
+ animation = SpringAnimation(animation: keyboardAnimation, fromValue: fromValue, toValue: toValue)
277
+ }
278
+
279
+ @objc func updateKeyboardFrame(link: CADisplayLink) {
267
280
  if keyboardView == nil {
268
281
  return
269
282
  }
270
283
 
271
284
  let keyboardFrameY = keyboardView?.layer.presentation()?.frame.origin.y ?? 0
272
285
  let keyboardWindowH = keyboardView?.window?.bounds.size.height ?? 0
273
- let keyboardPosition = keyboardWindowH - keyboardFrameY
286
+ var keyboardPosition = keyboardWindowH - keyboardFrameY
274
287
 
275
288
  if keyboardPosition == prevKeyboardPosition || keyboardFrameY == 0 {
276
289
  return
277
290
  }
278
291
 
279
292
  prevKeyboardPosition = keyboardPosition
293
+
294
+ if let animation = animation {
295
+ let baseDuration = animation.timingAt(value: keyboardPosition)
296
+
297
+ #if targetEnvironment(simulator)
298
+ // on iOS simulator we can not use static interval
299
+ // (from my observation from frame to frame we may have different delays)
300
+ // so for now we use approximation - we add a difference as
301
+ // beginTime - keyboardEventTime (but only in 0..0.016 range)
302
+ // and it gives satisfactory results (better than static delays)
303
+ let duration = baseDuration + animation.diff
304
+ #else
305
+ // 2 frames because we read previous frame, but need to calculate the next frame
306
+ let duration = baseDuration + link.duration * 2
307
+ #endif
308
+
309
+ let position = CGFloat(animation.valueAt(time: duration))
310
+
311
+ // handles a case when final frame has final destination (i. e. 0 or 291)
312
+ // but CASpringAnimation can never get to this final destination
313
+ let race: (CGFloat, CGFloat) -> CGFloat = animation.isIncreasing ? max : min
314
+ keyboardPosition = race(position, keyboardPosition)
315
+ }
316
+
280
317
  onEvent(
281
318
  "onKeyboardMove",
282
319
  keyboardPosition as NSNumber,
@@ -10,6 +10,7 @@
10
10
  #ifdef RCT_NEW_ARCH_ENABLED
11
11
  #import "KeyboardControllerView.h"
12
12
  #import "FocusedInputLayoutChangedEvent.h"
13
+ #import "FocusedInputSelectionChangedEvent.h"
13
14
  #import "FocusedInputTextChangedEvent.h"
14
15
  #import "KeyboardMoveEvent.h"
15
16
 
@@ -57,7 +58,7 @@ using namespace facebook::react;
57
58
  int target = [event[@"target"] integerValue];
58
59
  int parentScrollViewTarget = [event[@"parentScrollViewTarget"] integerValue];
59
60
  double absoluteY = [event[@"layout"][@"absoluteY"] doubleValue];
60
- double absoulteX = [event[@"layout"][@"absoluteX"] doubleValue];
61
+ double absoluteX = [event[@"layout"][@"absoluteX"] doubleValue];
61
62
  double y = [event[@"layout"][@"y"] doubleValue];
62
63
  double x = [event[@"layout"][@"x"] doubleValue];
63
64
  double width = [event[@"layout"][@"width"] doubleValue];
@@ -73,15 +74,15 @@ using namespace facebook::react;
73
74
  .layout = facebook::react::KeyboardControllerViewEventEmitter::
74
75
  OnFocusedInputLayoutChangedLayout{
75
76
  .absoluteY = absoluteY,
76
- .absoluteX = absoulteX,
77
+ .absoluteX = absoluteX,
77
78
  .height = height,
78
79
  .width = width,
79
80
  .x = x,
80
81
  .y = y}});
81
82
  // TODO: use built-in _eventEmitter once NativeAnimated module will use
82
- // ModernEventemitter
83
+ // ModernEventEmitter
83
84
  RCTBridge *bridge = [RCTBridge currentBridge];
84
- if (bridge && [bridge valueForKey:@"_jsThread"]) {
85
+ if (bridge) {
85
86
  FocusedInputLayoutChangedEvent *inputChangedEvent =
86
87
  [[FocusedInputLayoutChangedEvent alloc] initWithReactTag:@(self.tag) event:event];
87
88
  [bridge.eventDispatcher sendEvent:inputChangedEvent];
@@ -97,15 +98,51 @@ using namespace facebook::react;
97
98
  .text = std::string([text UTF8String])});
98
99
 
99
100
  // TODO: use built-in _eventEmitter once NativeAnimated module will use
100
- // ModernEventemitter
101
+ // ModernEventEmitter
101
102
  RCTBridge *bridge = [RCTBridge currentBridge];
102
- if (bridge && [bridge valueForKey:@"_jsThread"]) {
103
+ if (bridge) {
103
104
  FocusedInputTextChangedEvent *textChangedEvent =
104
105
  [[FocusedInputTextChangedEvent alloc] initWithReactTag:@(self.tag) text:text];
105
106
  [bridge.eventDispatcher sendEvent:textChangedEvent];
106
107
  }
107
108
  }
108
109
  }
110
+ onSelectionChangedHandler:^(NSDictionary *event) {
111
+ if (self->_eventEmitter) {
112
+ int target = [event[@"target"] integerValue];
113
+ double startX = [event[@"selection"][@"start"][@"x"] doubleValue];
114
+ double startY = [event[@"selection"][@"start"][@"y"] doubleValue];
115
+ double endX = [event[@"selection"][@"end"][@"x"] doubleValue];
116
+ double endY = [event[@"selection"][@"end"][@"y"] doubleValue];
117
+ int start = [event[@"selection"][@"start"][@"position"] integerValue];
118
+ int end = [event[@"selection"][@"end"][@"position"] integerValue];
119
+
120
+ std::dynamic_pointer_cast<const facebook::react::KeyboardControllerViewEventEmitter>(
121
+ self->_eventEmitter)
122
+ ->onFocusedInputSelectionChanged(
123
+ facebook::react::KeyboardControllerViewEventEmitter::
124
+ OnFocusedInputSelectionChanged{
125
+ .target = target,
126
+ .selection = facebook::react::KeyboardControllerViewEventEmitter::
127
+ OnFocusedInputSelectionChangedSelection{
128
+ .start =
129
+ facebook::react::KeyboardControllerViewEventEmitter::
130
+ OnFocusedInputSelectionChangedSelectionStart{
131
+ .x = startX, .y = startY, .position = start},
132
+ .end = facebook::react::KeyboardControllerViewEventEmitter::
133
+ OnFocusedInputSelectionChangedSelectionEnd{
134
+ .x = endX, .y = endY, .position = end}}});
135
+ // TODO: use built-in _eventEmitter once NativeAnimated module will use
136
+ // ModernEventEmitter
137
+ RCTBridge *bridge = [RCTBridge currentBridge];
138
+ if (bridge) {
139
+ FocusedInputSelectionChangedEvent *selectionChangedEvent =
140
+ [[FocusedInputSelectionChangedEvent alloc] initWithReactTag:@(self.tag)
141
+ event:event];
142
+ [bridge.eventDispatcher sendEvent:selectionChangedEvent];
143
+ }
144
+ }
145
+ }
109
146
  onFocusDidSet:^(NSDictionary *data) {
110
147
  [KeyboardController.shared sendEvent:@"KeyboardController::focusDidSet" body:data];
111
148
  }];
@@ -160,9 +197,9 @@ using namespace facebook::react;
160
197
  .target = [target intValue]});
161
198
  }
162
199
 
163
- // TODO: use built-in _eventEmitter once NativeAnimated module will use ModernEventemitter
200
+ // TODO: use built-in _eventEmitter once NativeAnimated module will use ModernEventEmitter
164
201
  RCTBridge *bridge = [RCTBridge currentBridge];
165
- if (bridge && [bridge valueForKey:@"_jsThread"]) {
202
+ if (bridge) {
166
203
  KeyboardMoveEvent *keyboardMoveEvent =
167
204
  [[KeyboardMoveEvent alloc] initWithReactTag:@(self.tag)
168
205
  event:event
@@ -14,5 +14,6 @@ RCT_EXPORT_VIEW_PROPERTY(onKeyboardMoveInteractive, RCTDirectEventBlock);
14
14
  /// input callbacks
15
15
  RCT_EXPORT_VIEW_PROPERTY(onFocusedInputLayoutChanged, RCTDirectEventBlock);
16
16
  RCT_EXPORT_VIEW_PROPERTY(onFocusedInputTextChanged, RCTDirectEventBlock);
17
+ RCT_EXPORT_VIEW_PROPERTY(onFocusedInputSelectionChanged, RCTDirectEventBlock);
17
18
 
18
19
  @end
@@ -24,6 +24,7 @@ class KeyboardControllerView: UIView {
24
24
  /// focused input
25
25
  @objc var onFocusedInputLayoutChanged: RCTDirectEventBlock?
26
26
  @objc var onFocusedInputTextChanged: RCTDirectEventBlock?
27
+ @objc var onFocusedInputSelectionChanged: RCTDirectEventBlock?
27
28
  // react props
28
29
  @objc var enabled: ObjCBool = true {
29
30
  didSet {
@@ -42,6 +43,7 @@ class KeyboardControllerView: UIView {
42
43
  inputObserver = FocusedInputObserver(
43
44
  onLayoutChangedHandler: { [weak self] event in self?.onLayoutChanged(event: event) },
44
45
  onTextChangedHandler: { [weak self] text in self?.onTextChanged(text: text) },
46
+ onSelectionChangedHandler: { [weak self] event in self?.onSelectionChanged(event: event) },
45
47
  onFocusDidSet: { [weak self] event in
46
48
  self?.onNotify(event: "KeyboardController::focusDidSet", data: event)
47
49
  }
@@ -93,6 +95,12 @@ class KeyboardControllerView: UIView {
93
95
  eventDispatcher.send(FocusedInputTextChangedEvent(reactTag: reactTag, text: text))
94
96
  }
95
97
 
98
+ func onSelectionChanged(event: NSObject) {
99
+ guard isJSThreadReady() else { return }
100
+
101
+ eventDispatcher.send(FocusedInputSelectionChangedEvent(reactTag: reactTag, event: event))
102
+ }
103
+
96
104
  func onEvent(event: NSString, height: NSNumber, progress: NSNumber, duration: NSNumber, target: NSNumber) {
97
105
  guard isJSThreadReady() else { return }
98
106
 
@@ -109,11 +117,11 @@ class KeyboardControllerView: UIView {
109
117
  }
110
118
 
111
119
  func onRequestAnimation() {
112
- bridge.uiManager.scheduleKeyboardAnimation()
120
+ // bridge.uiManager.scheduleKeyboardAnimation()
113
121
  }
114
122
 
115
123
  func onCancelAnimation() {
116
- bridge.uiManager.unscheduleKeyboardAnimation()
124
+ // bridge.uiManager.unscheduleKeyboardAnimation()
117
125
  }
118
126
 
119
127
  func onNotify(event: String, data: Any) {
@@ -127,6 +127,13 @@ const KeyboardProvider = ({
127
127
  broadcastInputEvents("onChangeText", e);
128
128
  }
129
129
  }, []);
130
+ const inputSelectionHandler = (0, _reanimated.useFocusedInputSelectionHandler)({
131
+ onFocusedInputSelectionChanged: e => {
132
+ "worklet";
133
+
134
+ broadcastInputEvents("onSelectionChange", e);
135
+ }
136
+ }, []);
130
137
  // effects
131
138
  (0, _react.useEffect)(() => {
132
139
  if (enabled) {
@@ -145,6 +152,7 @@ const KeyboardProvider = ({
145
152
  onKeyboardMoveInteractive: onKeyboardMove,
146
153
  onFocusedInputLayoutChangedReanimated: inputLayoutHandler,
147
154
  onFocusedInputTextChangedReanimated: inputTextHandler,
155
+ onFocusedInputSelectionChangedReanimated: inputSelectionHandler,
148
156
  navigationBarTranslucent: navigationBarTranslucent,
149
157
  statusBarTranslucent: statusBarTranslucent,
150
158
  style: styles.container
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_bindings","_context","_internal","_monkeyPatch","_reanimated","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","KeyboardControllerViewAnimated","Reanimated","createAnimatedComponent","Animated","KeyboardControllerView","styles","StyleSheet","create","container","flex","hidden","display","position","OS","Platform","KeyboardProvider","children","statusBarTranslucent","navigationBarTranslucent","enabled","initiallyEnabled","setEnabled","useState","progress","useAnimatedValue","height","progressSV","useSharedValue","heightSV","layout","setKeyboardHandlers","broadcastKeyboardEvents","useSharedHandlers","setInputHandlers","broadcastInputEvents","context","useMemo","animated","multiply","reanimated","style","transform","translateX","translateY","onKeyboardMove","event","nativeEvent","useNativeDriver","updateSharedValues","platforms","includes","value","keyboardHandler","useAnimatedKeyboardHandler","onKeyboardMoveStart","onKeyboardMoveEnd","onKeyboardMoveInteractive","inputLayoutHandler","useFocusedInputLayoutHandler","onFocusedInputLayoutChanged","target","inputTextHandler","useFocusedInputTextHandler","onFocusedInputTextChanged","useEffect","applyMonkeyPatch","revertMonkeyPatch","createElement","KeyboardContext","Provider","onKeyboardMoveReanimated","undefined","onFocusedInputLayoutChangedReanimated","onFocusedInputTextChangedReanimated","View","exports"],"sources":["animated.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from \"react\";\nimport { Animated, Platform, StyleSheet } from \"react-native\";\nimport Reanimated, { useSharedValue } from \"react-native-reanimated\";\n\nimport { KeyboardControllerView } from \"./bindings\";\nimport { KeyboardContext } from \"./context\";\nimport { useAnimatedValue, useSharedHandlers } from \"./internal\";\nimport { applyMonkeyPatch, revertMonkeyPatch } from \"./monkey-patch\";\nimport {\n useAnimatedKeyboardHandler,\n useFocusedInputLayoutHandler,\n useFocusedInputTextHandler,\n} from \"./reanimated\";\n\nimport type { KeyboardAnimationContext } from \"./context\";\nimport type {\n FocusedInputHandler,\n FocusedInputLayoutChangedEvent,\n KeyboardControllerProps,\n KeyboardHandler,\n NativeEvent,\n} from \"./types\";\nimport type { ViewStyle } from \"react-native\";\n\nconst KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(\n Animated.createAnimatedComponent(\n KeyboardControllerView,\n ) as React.FC<KeyboardControllerProps>,\n);\n\ntype Styles = {\n container: ViewStyle;\n hidden: ViewStyle;\n};\n\nconst styles = StyleSheet.create<Styles>({\n container: {\n flex: 1,\n },\n hidden: {\n display: \"none\",\n position: \"absolute\",\n },\n});\n\ntype KeyboardProviderProps = {\n children: React.ReactNode;\n /**\n * Set the value to `true`, if you use translucent status bar on Android.\n * If you already control status bar translucency via `react-native-screens`\n * or `StatusBar` component from `react-native`, you can ignore it.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/14\n * @platform android\n */\n statusBarTranslucent?: boolean;\n /**\n * Set the value to `true`, if you use translucent navigation bar on Android.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/119\n * @platform android\n */\n navigationBarTranslucent?: boolean;\n /**\n * A boolean prop indicating whether the module is enabled. It indicate only initial state,\n * i. e. if you try to change this prop after component mount it will not have any effect.\n * To change the property in runtime use `useKeyboardController` hook and `setEnabled` method.\n * Defaults to `true`.\n */\n enabled?: boolean;\n};\n\n// capture `Platform.OS` in separate variable to avoid deep workletization of entire RN package\n// see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/393 and https://github.com/kirillzyusko/react-native-keyboard-controller/issues/294 for more details\nconst OS = Platform.OS;\n\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n navigationBarTranslucent,\n enabled: initiallyEnabled = true,\n}: KeyboardProviderProps) => {\n // state\n const [enabled, setEnabled] = useState(initiallyEnabled);\n // animated values\n const progress = useAnimatedValue(0);\n const height = useAnimatedValue(0);\n // shared values\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n const layout = useSharedValue<FocusedInputLayoutChangedEvent | null>(null);\n const [setKeyboardHandlers, broadcastKeyboardEvents] =\n useSharedHandlers<KeyboardHandler>();\n const [setInputHandlers, broadcastInputEvents] =\n useSharedHandlers<FocusedInputHandler>();\n // memo\n const context = useMemo<KeyboardAnimationContext>(\n () => ({\n enabled,\n animated: { progress: progress, height: Animated.multiply(height, -1) },\n reanimated: { progress: progressSV, height: heightSV },\n layout,\n setKeyboardHandlers,\n setInputHandlers,\n setEnabled,\n }),\n [enabled],\n );\n const style = useMemo(\n () => [\n styles.hidden,\n { transform: [{ translateX: height }, { translateY: progress }] },\n ],\n [],\n );\n const onKeyboardMove = useMemo(\n () =>\n Animated.event(\n [\n {\n nativeEvent: {\n progress,\n height,\n },\n },\n ],\n { useNativeDriver: true },\n ),\n [],\n );\n // handlers\n const updateSharedValues = (event: NativeEvent, platforms: string[]) => {\n \"worklet\";\n\n if (platforms.includes(OS)) {\n progressSV.value = event.progress;\n heightSV.value = -event.height;\n }\n };\n const keyboardHandler = useAnimatedKeyboardHandler(\n {\n onKeyboardMoveStart: (event: NativeEvent) => {\n \"worklet\";\n\n broadcastKeyboardEvents(\"onStart\", event);\n updateSharedValues(event, [\"ios\"]);\n },\n onKeyboardMove: (event: NativeEvent) => {\n \"worklet\";\n\n broadcastKeyboardEvents(\"onMove\", event);\n updateSharedValues(event, [\"android\"]);\n },\n onKeyboardMoveEnd: (event: NativeEvent) => {\n \"worklet\";\n\n broadcastKeyboardEvents(\"onEnd\", event);\n },\n onKeyboardMoveInteractive: (event: NativeEvent) => {\n \"worklet\";\n\n updateSharedValues(event, [\"android\", \"ios\"]);\n broadcastKeyboardEvents(\"onInteractive\", event);\n },\n },\n [],\n );\n const inputLayoutHandler = useFocusedInputLayoutHandler(\n {\n onFocusedInputLayoutChanged: (e) => {\n \"worklet\";\n\n if (e.target !== -1) {\n layout.value = e;\n } else {\n layout.value = null;\n }\n },\n },\n [],\n );\n const inputTextHandler = useFocusedInputTextHandler(\n {\n onFocusedInputTextChanged: (e) => {\n \"worklet\";\n\n broadcastInputEvents(\"onChangeText\", e);\n },\n },\n [],\n );\n // effects\n useEffect(() => {\n if (enabled) {\n applyMonkeyPatch();\n } else {\n revertMonkeyPatch();\n }\n }, [enabled]);\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n enabled={enabled}\n onKeyboardMoveReanimated={keyboardHandler}\n onKeyboardMoveStart={OS === \"ios\" ? onKeyboardMove : undefined}\n onKeyboardMove={OS === \"android\" ? onKeyboardMove : undefined}\n onKeyboardMoveInteractive={onKeyboardMove}\n onFocusedInputLayoutChangedReanimated={inputLayoutHandler}\n onFocusedInputTextChangedReanimated={inputTextHandler}\n navigationBarTranslucent={navigationBarTranslucent}\n statusBarTranslucent={statusBarTranslucent}\n style={styles.container}\n >\n {children}\n </KeyboardControllerViewAnimated>\n <Animated.View\n // we are using this small hack, because if the component (where\n // animated value has been used) is unmounted, then animation will\n // stop receiving events (seems like it's react-native optimization).\n // So we need to keep a reference to the animated value, to keep it's\n // always mounted (keep a reference to an animated value).\n //\n // To test why it's needed, try to open screen which consumes Animated.Value\n // then close it and open it again (for example 'Animated transition').\n style={style}\n />\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_bindings","_context","_internal","_monkeyPatch","_reanimated","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","KeyboardControllerViewAnimated","Reanimated","createAnimatedComponent","Animated","KeyboardControllerView","styles","StyleSheet","create","container","flex","hidden","display","position","OS","Platform","KeyboardProvider","children","statusBarTranslucent","navigationBarTranslucent","enabled","initiallyEnabled","setEnabled","useState","progress","useAnimatedValue","height","progressSV","useSharedValue","heightSV","layout","setKeyboardHandlers","broadcastKeyboardEvents","useSharedHandlers","setInputHandlers","broadcastInputEvents","context","useMemo","animated","multiply","reanimated","style","transform","translateX","translateY","onKeyboardMove","event","nativeEvent","useNativeDriver","updateSharedValues","platforms","includes","value","keyboardHandler","useAnimatedKeyboardHandler","onKeyboardMoveStart","onKeyboardMoveEnd","onKeyboardMoveInteractive","inputLayoutHandler","useFocusedInputLayoutHandler","onFocusedInputLayoutChanged","target","inputTextHandler","useFocusedInputTextHandler","onFocusedInputTextChanged","inputSelectionHandler","useFocusedInputSelectionHandler","onFocusedInputSelectionChanged","useEffect","applyMonkeyPatch","revertMonkeyPatch","createElement","KeyboardContext","Provider","onKeyboardMoveReanimated","undefined","onFocusedInputLayoutChangedReanimated","onFocusedInputTextChangedReanimated","onFocusedInputSelectionChangedReanimated","View","exports"],"sources":["animated.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from \"react\";\nimport { Animated, Platform, StyleSheet } from \"react-native\";\nimport Reanimated, { useSharedValue } from \"react-native-reanimated\";\n\nimport { KeyboardControllerView } from \"./bindings\";\nimport { KeyboardContext } from \"./context\";\nimport { useAnimatedValue, useSharedHandlers } from \"./internal\";\nimport { applyMonkeyPatch, revertMonkeyPatch } from \"./monkey-patch\";\nimport {\n useAnimatedKeyboardHandler,\n useFocusedInputLayoutHandler,\n useFocusedInputSelectionHandler,\n useFocusedInputTextHandler,\n} from \"./reanimated\";\n\nimport type { KeyboardAnimationContext } from \"./context\";\nimport type {\n FocusedInputHandler,\n FocusedInputLayoutChangedEvent,\n KeyboardControllerProps,\n KeyboardHandler,\n NativeEvent,\n} from \"./types\";\nimport type { ViewStyle } from \"react-native\";\n\nconst KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(\n Animated.createAnimatedComponent(\n KeyboardControllerView,\n ) as React.FC<KeyboardControllerProps>,\n);\n\ntype Styles = {\n container: ViewStyle;\n hidden: ViewStyle;\n};\n\nconst styles = StyleSheet.create<Styles>({\n container: {\n flex: 1,\n },\n hidden: {\n display: \"none\",\n position: \"absolute\",\n },\n});\n\ntype KeyboardProviderProps = {\n children: React.ReactNode;\n /**\n * Set the value to `true`, if you use translucent status bar on Android.\n * If you already control status bar translucency via `react-native-screens`\n * or `StatusBar` component from `react-native`, you can ignore it.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/14\n * @platform android\n */\n statusBarTranslucent?: boolean;\n /**\n * Set the value to `true`, if you use translucent navigation bar on Android.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/119\n * @platform android\n */\n navigationBarTranslucent?: boolean;\n /**\n * A boolean prop indicating whether the module is enabled. It indicate only initial state,\n * i. e. if you try to change this prop after component mount it will not have any effect.\n * To change the property in runtime use `useKeyboardController` hook and `setEnabled` method.\n * Defaults to `true`.\n */\n enabled?: boolean;\n};\n\n// capture `Platform.OS` in separate variable to avoid deep workletization of entire RN package\n// see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/393 and https://github.com/kirillzyusko/react-native-keyboard-controller/issues/294 for more details\nconst OS = Platform.OS;\n\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n navigationBarTranslucent,\n enabled: initiallyEnabled = true,\n}: KeyboardProviderProps) => {\n // state\n const [enabled, setEnabled] = useState(initiallyEnabled);\n // animated values\n const progress = useAnimatedValue(0);\n const height = useAnimatedValue(0);\n // shared values\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n const layout = useSharedValue<FocusedInputLayoutChangedEvent | null>(null);\n const [setKeyboardHandlers, broadcastKeyboardEvents] =\n useSharedHandlers<KeyboardHandler>();\n const [setInputHandlers, broadcastInputEvents] =\n useSharedHandlers<FocusedInputHandler>();\n // memo\n const context = useMemo<KeyboardAnimationContext>(\n () => ({\n enabled,\n animated: { progress: progress, height: Animated.multiply(height, -1) },\n reanimated: { progress: progressSV, height: heightSV },\n layout,\n setKeyboardHandlers,\n setInputHandlers,\n setEnabled,\n }),\n [enabled],\n );\n const style = useMemo(\n () => [\n styles.hidden,\n { transform: [{ translateX: height }, { translateY: progress }] },\n ],\n [],\n );\n const onKeyboardMove = useMemo(\n () =>\n Animated.event(\n [\n {\n nativeEvent: {\n progress,\n height,\n },\n },\n ],\n { useNativeDriver: true },\n ),\n [],\n );\n // handlers\n const updateSharedValues = (event: NativeEvent, platforms: string[]) => {\n \"worklet\";\n\n if (platforms.includes(OS)) {\n progressSV.value = event.progress;\n heightSV.value = -event.height;\n }\n };\n const keyboardHandler = useAnimatedKeyboardHandler(\n {\n onKeyboardMoveStart: (event: NativeEvent) => {\n \"worklet\";\n\n broadcastKeyboardEvents(\"onStart\", event);\n updateSharedValues(event, [\"ios\"]);\n },\n onKeyboardMove: (event: NativeEvent) => {\n \"worklet\";\n\n broadcastKeyboardEvents(\"onMove\", event);\n updateSharedValues(event, [\"android\"]);\n },\n onKeyboardMoveEnd: (event: NativeEvent) => {\n \"worklet\";\n\n broadcastKeyboardEvents(\"onEnd\", event);\n },\n onKeyboardMoveInteractive: (event: NativeEvent) => {\n \"worklet\";\n\n updateSharedValues(event, [\"android\", \"ios\"]);\n broadcastKeyboardEvents(\"onInteractive\", event);\n },\n },\n [],\n );\n const inputLayoutHandler = useFocusedInputLayoutHandler(\n {\n onFocusedInputLayoutChanged: (e) => {\n \"worklet\";\n\n if (e.target !== -1) {\n layout.value = e;\n } else {\n layout.value = null;\n }\n },\n },\n [],\n );\n const inputTextHandler = useFocusedInputTextHandler(\n {\n onFocusedInputTextChanged: (e) => {\n \"worklet\";\n\n broadcastInputEvents(\"onChangeText\", e);\n },\n },\n [],\n );\n const inputSelectionHandler = useFocusedInputSelectionHandler(\n {\n onFocusedInputSelectionChanged: (e) => {\n \"worklet\";\n\n broadcastInputEvents(\"onSelectionChange\", e);\n },\n },\n [],\n );\n // effects\n useEffect(() => {\n if (enabled) {\n applyMonkeyPatch();\n } else {\n revertMonkeyPatch();\n }\n }, [enabled]);\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n enabled={enabled}\n onKeyboardMoveReanimated={keyboardHandler}\n onKeyboardMoveStart={OS === \"ios\" ? onKeyboardMove : undefined}\n onKeyboardMove={OS === \"android\" ? onKeyboardMove : undefined}\n onKeyboardMoveInteractive={onKeyboardMove}\n onFocusedInputLayoutChangedReanimated={inputLayoutHandler}\n onFocusedInputTextChangedReanimated={inputTextHandler}\n onFocusedInputSelectionChangedReanimated={inputSelectionHandler}\n navigationBarTranslucent={navigationBarTranslucent}\n statusBarTranslucent={statusBarTranslucent}\n style={styles.container}\n >\n {children}\n </KeyboardControllerViewAnimated>\n <Animated.View\n // we are using this small hack, because if the component (where\n // animated value has been used) is unmounted, then animation will\n // stop receiving events (seems like it's react-native optimization).\n // So we need to keep a reference to the animated value, to keep it's\n // always mounted (keep a reference to an animated value).\n //\n // To test why it's needed, try to open screen which consumes Animated.Value\n // then close it and open it again (for example 'Animated transition').\n style={style}\n />\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":"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","ignoreList":[]}