react-native-keyboard-controller 1.3.0 → 1.4.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 (48) hide show
  1. package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardAnimationCallback.kt +8 -4
  2. package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManagerImpl.kt +6 -3
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/events/KeyboardTransitionEvent.kt +2 -6
  4. package/ios/.swiftlint.yml +4 -0
  5. package/ios/KeyboardControllerView.mm +24 -6
  6. package/ios/KeyboardControllerViewManager.mm +2 -0
  7. package/ios/KeyboardControllerViewManager.swift +4 -1
  8. package/ios/KeyboardMoveEvent.h +1 -0
  9. package/ios/KeyboardMoveEvent.m +2 -1
  10. package/ios/KeyboardMovementObserver.swift +89 -4
  11. package/lib/commonjs/animated.js +32 -6
  12. package/lib/commonjs/animated.js.map +1 -1
  13. package/lib/commonjs/context.js +2 -1
  14. package/lib/commonjs/context.js.map +1 -1
  15. package/lib/commonjs/hooks.js +26 -1
  16. package/lib/commonjs/hooks.js.map +1 -1
  17. package/lib/commonjs/internal.js +66 -2
  18. package/lib/commonjs/internal.js.map +1 -1
  19. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  20. package/lib/commonjs/types.js.map +1 -1
  21. package/lib/commonjs/utils.js +11 -0
  22. package/lib/commonjs/utils.js.map +1 -0
  23. package/lib/module/animated.js +34 -8
  24. package/lib/module/animated.js.map +1 -1
  25. package/lib/module/context.js +2 -1
  26. package/lib/module/context.js.map +1 -1
  27. package/lib/module/hooks.js +19 -0
  28. package/lib/module/hooks.js.map +1 -1
  29. package/lib/module/internal.js +64 -3
  30. package/lib/module/internal.js.map +1 -1
  31. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  32. package/lib/module/types.js.map +1 -1
  33. package/lib/module/utils.js +2 -0
  34. package/lib/module/utils.js.map +1 -0
  35. package/lib/typescript/context.d.ts +3 -1
  36. package/lib/typescript/hooks.d.ts +4 -0
  37. package/lib/typescript/internal.d.ts +18 -1
  38. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +2 -0
  39. package/lib/typescript/types.d.ts +10 -1
  40. package/lib/typescript/utils.d.ts +1 -0
  41. package/package.json +1 -1
  42. package/src/animated.tsx +34 -7
  43. package/src/context.ts +4 -1
  44. package/src/hooks.ts +29 -1
  45. package/src/internal.ts +64 -4
  46. package/src/specs/KeyboardControllerViewNativeComponent.ts +4 -0
  47. package/src/types.ts +19 -1
  48. package/src/utils.ts +1 -0
@@ -74,14 +74,16 @@ class KeyboardAnimationCallback(
74
74
  val keyboardHeight = getCurrentKeyboardHeight()
75
75
 
76
76
  this.emitEvent("KeyboardController::keyboardWillShow", getEventParams(keyboardHeight))
77
+ this.sendEventToJS(KeyboardTransitionEvent(view.id, "topKeyboardMoveStart", keyboardHeight, 1.0))
77
78
 
78
- val animation = ValueAnimator.ofInt(-this.persistentKeyboardHeight, -keyboardHeight)
79
+ val animation = ValueAnimator.ofInt(this.persistentKeyboardHeight, keyboardHeight)
79
80
  animation.addUpdateListener { animator ->
80
81
  val toValue = animator.animatedValue as Int
81
- this.sendEventToJS(KeyboardTransitionEvent(view.id, toValue, -toValue.toDouble() / keyboardHeight))
82
+ this.sendEventToJS(KeyboardTransitionEvent(view.id, "topKeyboardMove", toValue, toValue.toDouble() / keyboardHeight))
82
83
  }
83
84
  animation.doOnEnd {
84
85
  this.emitEvent("KeyboardController::keyboardDidShow", getEventParams(keyboardHeight))
86
+ this.sendEventToJS(KeyboardTransitionEvent(view.id, "topKeyboardMoveEnd", keyboardHeight, 1.0))
85
87
  }
86
88
  animation.setDuration(250).startDelay = 0
87
89
  animation.start()
@@ -108,6 +110,7 @@ class KeyboardAnimationCallback(
108
110
  this.emitEvent("KeyboardController::" + if (!isKeyboardVisible) "keyboardWillHide" else "keyboardWillShow", getEventParams(keyboardHeight))
109
111
 
110
112
  Log.i(TAG, "HEIGHT:: $keyboardHeight")
113
+ this.sendEventToJS(KeyboardTransitionEvent(view.id, "topKeyboardMoveStart", keyboardHeight, if (!isKeyboardVisible) 0.0 else 1.0))
111
114
 
112
115
  return super.onStart(animation, bounds)
113
116
  }
@@ -128,7 +131,7 @@ class KeyboardAnimationCallback(
128
131
  val diff = Insets.subtract(typesInset, otherInset).let {
129
132
  Insets.max(it, Insets.NONE)
130
133
  }
131
- val diffY = (diff.top - diff.bottom).toFloat()
134
+ val diffY = (diff.bottom - diff.top).toFloat()
132
135
  val height = toDp(diffY, context)
133
136
 
134
137
  var progress = 0.0
@@ -139,7 +142,7 @@ class KeyboardAnimationCallback(
139
142
  }
140
143
  Log.i(TAG, "DiffY: $diffY $height $progress")
141
144
 
142
- this.sendEventToJS(KeyboardTransitionEvent(view.id, height, progress))
145
+ this.sendEventToJS(KeyboardTransitionEvent(view.id, "topKeyboardMove", height, progress))
143
146
 
144
147
  return insets
145
148
  }
@@ -150,6 +153,7 @@ class KeyboardAnimationCallback(
150
153
  isTransitioning = false
151
154
  this.persistentKeyboardHeight = getCurrentKeyboardHeight()
152
155
  this.emitEvent("KeyboardController::" + if (!isKeyboardVisible) "keyboardDidHide" else "keyboardDidShow", getEventParams(this.persistentKeyboardHeight))
156
+ this.sendEventToJS(KeyboardTransitionEvent(view.id, "topKeyboardMoveEnd", this.persistentKeyboardHeight, if (!isKeyboardVisible) 0.0 else 1.0))
153
157
  }
154
158
 
155
159
  private fun isKeyboardVisible(): Boolean {
@@ -9,7 +9,6 @@ import com.facebook.react.bridge.ReactApplicationContext
9
9
  import com.facebook.react.common.MapBuilder
10
10
  import com.facebook.react.uimanager.ThemedReactContext
11
11
  import com.facebook.react.views.view.ReactViewGroup
12
- import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
13
12
 
14
13
  class KeyboardControllerViewManagerImpl(reactContext: ReactApplicationContext) {
15
14
  private val TAG = KeyboardControllerViewManagerImpl::class.qualifiedName
@@ -58,8 +57,12 @@ class KeyboardControllerViewManagerImpl(reactContext: ReactApplicationContext) {
58
57
 
59
58
  fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
60
59
  val map: MutableMap<String, Any> = MapBuilder.of(
61
- KeyboardTransitionEvent.EVENT_NAME,
62
- MapBuilder.of("registrationName", "onKeyboardMove")
60
+ "topKeyboardMove",
61
+ MapBuilder.of("registrationName", "onKeyboardMove"),
62
+ "topKeyboardMoveStart",
63
+ MapBuilder.of("registrationName", "onKeyboardMoveStart"),
64
+ "topKeyboardMoveEnd",
65
+ MapBuilder.of("registrationName", "onKeyboardMoveEnd"),
63
66
  )
64
67
 
65
68
  return map
@@ -4,8 +4,8 @@ import com.facebook.react.bridge.Arguments
4
4
  import com.facebook.react.uimanager.events.Event
5
5
  import com.facebook.react.uimanager.events.RCTEventEmitter
6
6
 
7
- class KeyboardTransitionEvent(private val viewId: Int, private val height: Int, private val progress: Double) : Event<KeyboardTransitionEvent>(viewId) {
8
- override fun getEventName() = EVENT_NAME
7
+ class KeyboardTransitionEvent(viewId: Int, private val event: String, private val height: Int, private val progress: Double) : Event<KeyboardTransitionEvent>(viewId) {
8
+ override fun getEventName() = event
9
9
 
10
10
  // TODO: All events for a given view can be coalesced?
11
11
  override fun getCoalescingKey(): Short = 0
@@ -16,8 +16,4 @@ class KeyboardTransitionEvent(private val viewId: Int, private val height: Int,
16
16
  map.putInt("height", height)
17
17
  rctEventEmitter.receiveEvent(viewTag, eventName, map)
18
18
  }
19
-
20
- companion object {
21
- const val EVENT_NAME = "topKeyboardMove"
22
- }
23
19
  }
@@ -1,5 +1,9 @@
1
1
  disabled_rules:
2
2
  - trailing_comma
3
3
 
4
+ line_length:
5
+ warning: 120
6
+ ignores_urls: true
7
+
4
8
  excluded:
5
9
  - Pods
@@ -44,13 +44,30 @@ using namespace facebook::react;
44
44
  _props = defaultProps;
45
45
 
46
46
  observer = [[KeyboardMovementObserver alloc]
47
- initWithHandler:^(NSNumber *height, NSNumber *progress) {
47
+ initWithHandler:^(NSString *event, NSNumber *height, NSNumber *progress) {
48
48
  if (self->_eventEmitter) {
49
- std::dynamic_pointer_cast<const facebook::react::KeyboardControllerViewEventEmitter>(
50
- self->_eventEmitter)
51
- ->onKeyboardMove(
52
- facebook::react::KeyboardControllerViewEventEmitter::OnKeyboardMove{
53
- .height = [height intValue], .progress = static_cast<Float>(self.tag)});
49
+ // TODO: use reflection to reduce code duplication?
50
+ if ([event isEqualToString:@"onKeyboardMoveStart"]) {
51
+ std::dynamic_pointer_cast<const facebook::react::KeyboardControllerViewEventEmitter>(
52
+ self->_eventEmitter)
53
+ ->onKeyboardMoveStart(
54
+ facebook::react::KeyboardControllerViewEventEmitter::OnKeyboardMoveStart{
55
+ .height = [height intValue], .progress = [progress floatValue]});
56
+ }
57
+ if ([event isEqualToString:@"onKeyboardMove"]) {
58
+ std::dynamic_pointer_cast<const facebook::react::KeyboardControllerViewEventEmitter>(
59
+ self->_eventEmitter)
60
+ ->onKeyboardMove(
61
+ facebook::react::KeyboardControllerViewEventEmitter::OnKeyboardMove{
62
+ .height = [height intValue], .progress = [progress floatValue]});
63
+ }
64
+ if ([event isEqualToString:@"onKeyboardMoveEnd"]) {
65
+ std::dynamic_pointer_cast<const facebook::react::KeyboardControllerViewEventEmitter>(
66
+ self->_eventEmitter)
67
+ ->onKeyboardMoveEnd(
68
+ facebook::react::KeyboardControllerViewEventEmitter::OnKeyboardMoveEnd{
69
+ .height = [height intValue], .progress = [progress floatValue]});
70
+ }
54
71
  }
55
72
 
56
73
  // TODO: use built-in _eventEmitter once NativeAnimated module will use ModernEventemitter
@@ -58,6 +75,7 @@ using namespace facebook::react;
58
75
  if (bridge) {
59
76
  KeyboardMoveEvent *keyboardMoveEvent =
60
77
  [[KeyboardMoveEvent alloc] initWithReactTag:@(self.tag)
78
+ event:event
61
79
  height:height
62
80
  progress:progress];
63
81
  [bridge.eventDispatcher sendEvent:keyboardMoveEvent];
@@ -2,6 +2,8 @@
2
2
 
3
3
  @interface RCT_EXTERN_MODULE (KeyboardControllerViewManager, RCTViewManager)
4
4
 
5
+ RCT_EXPORT_VIEW_PROPERTY(onKeyboardMoveStart, RCTDirectEventBlock);
5
6
  RCT_EXPORT_VIEW_PROPERTY(onKeyboardMove, RCTDirectEventBlock);
7
+ RCT_EXPORT_VIEW_PROPERTY(onKeyboardMoveEnd, RCTDirectEventBlock);
6
8
 
7
9
  @end
@@ -12,7 +12,9 @@ class KeyboardControllerViewManager: RCTViewManager {
12
12
  class KeyboardControllerView: UIView {
13
13
  private var keyboardObserver: KeyboardMovementObserver?
14
14
  private var eventDispatcher: RCTEventDispatcherProtocol
15
+ @objc var onKeyboardMoveStart: RCTDirectEventBlock?
15
16
  @objc var onKeyboardMove: RCTDirectEventBlock?
17
+ @objc var onKeyboardMoveEnd: RCTDirectEventBlock?
16
18
 
17
19
  init(frame: CGRect, eventDispatcher: RCTEventDispatcherProtocol) {
18
20
  self.eventDispatcher = eventDispatcher
@@ -39,10 +41,11 @@ class KeyboardControllerView: UIView {
39
41
  }
40
42
  }
41
43
 
42
- func onEvent(height: NSNumber, progress: NSNumber) {
44
+ func onEvent(event: NSString, height: NSNumber, progress: NSNumber) {
43
45
  eventDispatcher.send(
44
46
  KeyboardMoveEvent(
45
47
  reactTag: reactTag,
48
+ event: event as String,
46
49
  height: height,
47
50
  progress: progress
48
51
  )
@@ -12,6 +12,7 @@
12
12
  @interface KeyboardMoveEvent : NSObject <RCTEvent>
13
13
 
14
14
  - (instancetype)initWithReactTag:(NSNumber *)reactTag
15
+ event:(NSString *)event
15
16
  height:(NSNumber *)height
16
17
  progress:(NSNumber *)progress;
17
18
 
@@ -19,13 +19,14 @@
19
19
  @synthesize eventName = _eventName;
20
20
 
21
21
  - (instancetype)initWithReactTag:(NSNumber *)reactTag
22
+ event:(NSString *)event
22
23
  height:(NSNumber *)height
23
24
  progress:(NSNumber *)progress
24
25
  {
25
26
  RCTAssertParam(reactTag);
26
27
 
27
28
  if ((self = [super init])) {
28
- _eventName = @"onKeyboardMove";
29
+ _eventName = [event copy];
29
30
  _viewTag = reactTag;
30
31
  _progress = progress;
31
32
  _height = height;
@@ -10,10 +10,31 @@ import Foundation
10
10
 
11
11
  @objc(KeyboardMovementObserver)
12
12
  public class KeyboardMovementObserver: NSObject {
13
- var onEvent: (NSNumber, NSNumber) -> Void
13
+ // class members
14
+ var onEvent: (NSString, NSNumber, NSNumber) -> Void
14
15
  var onNotify: (String, Any) -> Void
16
+ // progress tracker
17
+ private var _keyboardView: UIView?
18
+ private var keyboardView: UIView? {
19
+ let windowsCount = UIApplication.shared.windows.count
15
20
 
16
- @objc public init(handler: @escaping (NSNumber, NSNumber) -> Void, onNotify: @escaping (String, Any) -> Void) {
21
+ if _keyboardView == nil || windowsCount != _windowsCount {
22
+ _keyboardView = findKeyboardView()
23
+ _windowsCount = windowsCount
24
+ }
25
+
26
+ return _keyboardView
27
+ }
28
+
29
+ private var _windowsCount: Int = 0
30
+ private var prevKeyboardPosition = 0.0
31
+ private var displayLink: CADisplayLink?
32
+ private var keyboardHeight: CGFloat = 0.0
33
+
34
+ @objc public init(
35
+ handler: @escaping (NSString, NSNumber, NSNumber) -> Void,
36
+ onNotify: @escaping (String, Any) -> Void
37
+ ) {
17
38
  onEvent = handler
18
39
  self.onNotify = onNotify
19
40
  }
@@ -53,12 +74,15 @@ public class KeyboardMovementObserver: NSObject {
53
74
  @objc func keyboardWillAppear(_ notification: Notification) {
54
75
  if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
55
76
  let keyboardHeight = keyboardFrame.cgRectValue.size.height
77
+ self.keyboardHeight = keyboardHeight
56
78
 
57
79
  var data = [AnyHashable: Any]()
58
80
  data["height"] = keyboardHeight
59
81
 
60
- onEvent(Float(-keyboardHeight) as NSNumber, 1)
82
+ onEvent("onKeyboardMoveStart", Float(keyboardHeight) as NSNumber, 1)
61
83
  onNotify("KeyboardController::keyboardWillShow", data)
84
+
85
+ setupKeyboardWatcher()
62
86
  }
63
87
  }
64
88
 
@@ -66,18 +90,24 @@ public class KeyboardMovementObserver: NSObject {
66
90
  var data = [AnyHashable: Any]()
67
91
  data["height"] = 0
68
92
 
69
- onEvent(0, 0)
93
+ onEvent("onKeyboardMoveStart", 0, 0)
70
94
  onNotify("KeyboardController::keyboardWillHide", data)
95
+
96
+ setupKeyboardWatcher()
71
97
  }
72
98
 
73
99
  @objc func keyboardDidAppear(_ notification: Notification) {
74
100
  if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
75
101
  let keyboardHeight = keyboardFrame.cgRectValue.size.height
102
+ self.keyboardHeight = keyboardHeight
76
103
 
77
104
  var data = [AnyHashable: Any]()
78
105
  data["height"] = keyboardHeight
79
106
 
107
+ onEvent("onKeyboardMoveEnd", keyboardHeight as NSNumber, 1)
80
108
  onNotify("KeyboardController::keyboardDidShow", data)
109
+
110
+ removeKeyboardWatcher()
81
111
  }
82
112
  }
83
113
 
@@ -85,6 +115,61 @@ public class KeyboardMovementObserver: NSObject {
85
115
  var data = [AnyHashable: Any]()
86
116
  data["height"] = 0
87
117
 
118
+ onEvent("onKeyboardMoveEnd", 0 as NSNumber, 0)
88
119
  onNotify("KeyboardController::keyboardDidHide", data)
120
+
121
+ removeKeyboardWatcher()
122
+ }
123
+
124
+ @objc func setupKeyboardWatcher() {
125
+ displayLink = CADisplayLink(target: self, selector: #selector(updateKeyboardFrame))
126
+ displayLink?.preferredFramesPerSecond = 120 // will fallback to 60 fps for devices without Pro Motion display
127
+ displayLink?.add(to: .main, forMode: .common)
128
+ }
129
+
130
+ @objc func removeKeyboardWatcher() {
131
+ displayLink?.invalidate()
132
+ displayLink = nil
133
+ }
134
+
135
+ // https://stackoverflow.com/questions/32598490/show-uiview-with-buttons-over-keyboard-like-in-skype-viber-messengers-swift-i
136
+ func findKeyboardView() -> UIView? {
137
+ var result: UIView?
138
+
139
+ let windows = UIApplication.shared.windows
140
+ for window in windows {
141
+ if window.description.hasPrefix("<UITextEffectsWindow") {
142
+ for subview in window.subviews {
143
+ if subview.description.hasPrefix("<UIInputSetContainerView") {
144
+ for hostView in subview.subviews {
145
+ if hostView.description.hasPrefix("<UIInputSetHostView") {
146
+ result = hostView as? UIView
147
+ break
148
+ }
149
+ }
150
+ break
151
+ }
152
+ }
153
+ break
154
+ }
155
+ }
156
+ return result
157
+ }
158
+
159
+ @objc func updateKeyboardFrame() {
160
+ if keyboardView == nil {
161
+ return
162
+ }
163
+
164
+ var keyboardFrameY = keyboardView?.layer.presentation()?.frame.origin.y ?? 0
165
+ var keyboardWindowH = keyboardView?.window?.bounds.size.height ?? 0
166
+ var keyboardPosition = keyboardWindowH - keyboardFrameY
167
+
168
+ if keyboardPosition == prevKeyboardPosition || keyboardFrameY == 0 {
169
+ return
170
+ }
171
+
172
+ prevKeyboardPosition = keyboardPosition
173
+ onEvent("onKeyboardMove", keyboardPosition as NSNumber, keyboardPosition / CGFloat(keyboardHeight) as NSNumber)
89
174
  }
90
175
  }
@@ -45,17 +45,22 @@ const KeyboardProvider = _ref => {
45
45
  const height = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current; // shared values
46
46
 
47
47
  const progressSV = (0, _reactNativeReanimated.useSharedValue)(0);
48
- const heightSV = (0, _reactNativeReanimated.useSharedValue)(0); // memo
48
+ const heightSV = (0, _reactNativeReanimated.useSharedValue)(0);
49
+ const {
50
+ setHandlers,
51
+ broadcast
52
+ } = (0, _internal.useSharedHandlers)(); // memo
49
53
 
50
54
  const context = (0, _react.useMemo)(() => ({
51
55
  animated: {
52
56
  progress: progress,
53
- height: height
57
+ height: _reactNative.Animated.multiply(height, -1)
54
58
  },
55
59
  reanimated: {
56
60
  progress: progressSV,
57
61
  height: heightSV
58
- }
62
+ },
63
+ setHandlers
59
64
  }), []);
60
65
  const style = (0, _react.useMemo)(() => [styles.hidden, {
61
66
  transform: [{
@@ -73,19 +78,40 @@ const KeyboardProvider = _ref => {
73
78
  useNativeDriver: true
74
79
  }), []); // handlers
75
80
 
81
+ const updateSharedValues = (event, platforms) => {
82
+ 'worklet';
83
+
84
+ if (platforms.includes(_reactNative.Platform.OS)) {
85
+ progressSV.value = event.progress;
86
+ heightSV.value = -event.height;
87
+ }
88
+ };
89
+
76
90
  const handler = (0, _internal.useAnimatedKeyboardHandler)({
91
+ onKeyboardMoveStart: event => {
92
+ 'worklet';
93
+
94
+ broadcast('onStart', event);
95
+ updateSharedValues(event, ['ios']);
96
+ },
77
97
  onKeyboardMove: event => {
78
98
  'worklet';
79
99
 
80
- progressSV.value = event.progress;
81
- heightSV.value = event.height;
100
+ broadcast('onMove', event);
101
+ updateSharedValues(event, ['android']);
102
+ },
103
+ onKeyboardMoveEnd: event => {
104
+ 'worklet';
105
+
106
+ broadcast('onEnd', event);
82
107
  }
83
108
  }, []);
84
109
  return /*#__PURE__*/_react.default.createElement(_context.KeyboardContext.Provider, {
85
110
  value: context
86
111
  }, /*#__PURE__*/_react.default.createElement(KeyboardControllerViewAnimated, {
87
112
  onKeyboardMoveReanimated: handler,
88
- onKeyboardMove: onKeyboardMove,
113
+ onKeyboardMoveStart: _reactNative.Platform.OS === 'ios' ? onKeyboardMove : undefined,
114
+ onKeyboardMove: _reactNative.Platform.OS === 'android' ? onKeyboardMove : undefined,
89
115
  statusBarTranslucent: statusBarTranslucent,
90
116
  style: styles.container
91
117
  }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, {
@@ -1 +1 @@
1
- {"version":3,"names":["KeyboardControllerViewAnimated","Reanimated","createAnimatedComponent","Animated","KeyboardControllerView","styles","StyleSheet","create","container","flex","hidden","display","position","KeyboardProvider","children","statusBarTranslucent","progress","useRef","Value","current","height","progressSV","useSharedValue","heightSV","context","useMemo","animated","reanimated","style","transform","translateX","translateY","onKeyboardMove","event","nativeEvent","useNativeDriver","handler","useAnimatedKeyboardHandler","value"],"sources":["animated.tsx"],"sourcesContent":["import React, { useMemo, useRef } from 'react';\nimport { Animated, StyleSheet, ViewStyle } from 'react-native';\nimport Reanimated, { useSharedValue } from 'react-native-reanimated';\n\nimport { KeyboardContext } from './context';\nimport { useAnimatedKeyboardHandler } from './internal';\nimport { KeyboardControllerView } from './native';\n\nimport type { KeyboardControllerProps, NativeEvent } from './types';\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\nexport const 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\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n}: KeyboardProviderProps) => {\n // animated values\n const progress = useRef(new Animated.Value(0)).current;\n const height = useRef(new Animated.Value(0)).current;\n // shared values\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n // memo\n const context = useMemo(\n () => ({\n animated: { progress: progress, height: height },\n reanimated: { progress: progressSV, height: heightSV },\n }),\n []\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 handler = useAnimatedKeyboardHandler(\n {\n onKeyboardMove: (event: NativeEvent) => {\n 'worklet';\n progressSV.value = event.progress;\n heightSV.value = event.height;\n },\n },\n []\n );\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n onKeyboardMoveReanimated={handler}\n onKeyboardMove={onKeyboardMove}\n statusBarTranslucent={statusBarTranslucent}\n style={styles.container}\n >\n <>\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 {children}\n </>\n </KeyboardControllerViewAnimated>\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":";;;;;;;AAAA;;AACA;;AACA;;AAEA;;AACA;;AACA;;;;;;AAIA,MAAMA,8BAA8B,GAAGC,8BAAA,CAAWC,uBAAX,CACrCC,qBAAA,CAASD,uBAAT,CACEE,8BADF,CADqC,CAAvC;;AAWO,MAAMC,MAAM,GAAGC,uBAAA,CAAWC,MAAX,CAA0B;EAC9CC,SAAS,EAAE;IACTC,IAAI,EAAE;EADG,CADmC;EAI9CC,MAAM,EAAE;IACNC,OAAO,EAAE,MADH;IAENC,QAAQ,EAAE;EAFJ;AAJsC,CAA1B,CAAf;;;;AAwBA,MAAMC,gBAAgB,GAAG,QAGH;EAAA,IAHI;IAC/BC,QAD+B;IAE/BC;EAF+B,CAGJ;EAC3B;EACA,MAAMC,QAAQ,GAAG,IAAAC,aAAA,EAAO,IAAId,qBAAA,CAASe,KAAb,CAAmB,CAAnB,CAAP,EAA8BC,OAA/C;EACA,MAAMC,MAAM,GAAG,IAAAH,aAAA,EAAO,IAAId,qBAAA,CAASe,KAAb,CAAmB,CAAnB,CAAP,EAA8BC,OAA7C,CAH2B,CAI3B;;EACA,MAAME,UAAU,GAAG,IAAAC,qCAAA,EAAe,CAAf,CAAnB;EACA,MAAMC,QAAQ,GAAG,IAAAD,qCAAA,EAAe,CAAf,CAAjB,CAN2B,CAO3B;;EACA,MAAME,OAAO,GAAG,IAAAC,cAAA,EACd,OAAO;IACLC,QAAQ,EAAE;MAAEV,QAAQ,EAAEA,QAAZ;MAAsBI,MAAM,EAAEA;IAA9B,CADL;IAELO,UAAU,EAAE;MAAEX,QAAQ,EAAEK,UAAZ;MAAwBD,MAAM,EAAEG;IAAhC;EAFP,CAAP,CADc,EAKd,EALc,CAAhB;EAOA,MAAMK,KAAK,GAAG,IAAAH,cAAA,EACZ,MAAM,CACJpB,MAAM,CAACK,MADH,EAEJ;IAAEmB,SAAS,EAAE,CAAC;MAAEC,UAAU,EAAEV;IAAd,CAAD,EAAyB;MAAEW,UAAU,EAAEf;IAAd,CAAzB;EAAb,CAFI,CADM,EAKZ,EALY,CAAd;EAOA,MAAMgB,cAAc,GAAG,IAAAP,cAAA,EACrB,MACEtB,qBAAA,CAAS8B,KAAT,CACE,CACE;IACEC,WAAW,EAAE;MACXlB,QADW;MAEXI;IAFW;EADf,CADF,CADF,EASE;IAAEe,eAAe,EAAE;EAAnB,CATF,CAFmB,EAarB,EAbqB,CAAvB,CAtB2B,CAqC3B;;EACA,MAAMC,OAAO,GAAG,IAAAC,oCAAA,EACd;IACEL,cAAc,EAAGC,KAAD,IAAwB;MACtC;;MACAZ,UAAU,CAACiB,KAAX,GAAmBL,KAAK,CAACjB,QAAzB;MACAO,QAAQ,CAACe,KAAT,GAAiBL,KAAK,CAACb,MAAvB;IACD;EALH,CADc,EAQd,EARc,CAAhB;EAWA,oBACE,6BAAC,wBAAD,CAAiB,QAAjB;IAA0B,KAAK,EAAEI;EAAjC,gBACE,6BAAC,8BAAD;IACE,wBAAwB,EAAEY,OAD5B;IAEE,cAAc,EAAEJ,cAFlB;IAGE,oBAAoB,EAAEjB,oBAHxB;IAIE,KAAK,EAAEV,MAAM,CAACG;EAJhB,gBAME,yEACE,6BAAC,qBAAD,CAAU,IAAV;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,KAAK,EAAEoB;EATT,EADF,EAYGd,QAZH,CANF,CADF,CADF;AAyBD,CA7EM"}
1
+ {"version":3,"names":["KeyboardControllerViewAnimated","Reanimated","createAnimatedComponent","Animated","KeyboardControllerView","styles","StyleSheet","create","container","flex","hidden","display","position","KeyboardProvider","children","statusBarTranslucent","progress","useRef","Value","current","height","progressSV","useSharedValue","heightSV","setHandlers","broadcast","useSharedHandlers","context","useMemo","animated","multiply","reanimated","style","transform","translateX","translateY","onKeyboardMove","event","nativeEvent","useNativeDriver","updateSharedValues","platforms","includes","Platform","OS","value","handler","useAnimatedKeyboardHandler","onKeyboardMoveStart","onKeyboardMoveEnd","undefined"],"sources":["animated.tsx"],"sourcesContent":["import React, { useMemo, useRef } from 'react';\nimport { Animated, Platform, StyleSheet, ViewStyle } from 'react-native';\nimport Reanimated, { useSharedValue } from 'react-native-reanimated';\n\nimport { KeyboardContext } from './context';\nimport { useAnimatedKeyboardHandler, useSharedHandlers } from './internal';\nimport { KeyboardControllerView } from './native';\n\nimport type {\n KeyboardControllerProps,\n KeyboardHandler,\n NativeEvent,\n} from './types';\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\nexport const 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\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n}: KeyboardProviderProps) => {\n // animated values\n const progress = useRef(new Animated.Value(0)).current;\n const height = useRef(new Animated.Value(0)).current;\n // shared values\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n const { setHandlers, broadcast } = useSharedHandlers<KeyboardHandler>();\n // memo\n const context = useMemo(\n () => ({\n animated: { progress: progress, height: Animated.multiply(height, -1) },\n reanimated: { progress: progressSV, height: heightSV },\n setHandlers,\n }),\n []\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(Platform.OS)) {\n progressSV.value = event.progress;\n heightSV.value = -event.height;\n }\n };\n const handler = useAnimatedKeyboardHandler(\n {\n onKeyboardMoveStart: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onStart', event);\n updateSharedValues(event, ['ios']);\n },\n onKeyboardMove: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onMove', event);\n updateSharedValues(event, ['android']);\n },\n onKeyboardMoveEnd: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onEnd', event);\n },\n },\n []\n );\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n onKeyboardMoveReanimated={handler}\n onKeyboardMoveStart={Platform.OS === 'ios' ? onKeyboardMove : undefined}\n onKeyboardMove={Platform.OS === 'android' ? onKeyboardMove : undefined}\n statusBarTranslucent={statusBarTranslucent}\n style={styles.container}\n >\n <>\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 {children}\n </>\n </KeyboardControllerViewAnimated>\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":"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"}
@@ -21,7 +21,8 @@ const defaultContext = {
21
21
  height: {
22
22
  value: 0
23
23
  }
24
- }
24
+ },
25
+ setHandlers: () => {}
25
26
  };
26
27
  const KeyboardContext = /*#__PURE__*/(0, _react.createContext)(defaultContext);
27
28
  exports.KeyboardContext = KeyboardContext;
@@ -1 +1 @@
1
- {"version":3,"names":["defaultContext","animated","progress","Animated","Value","height","reanimated","value","KeyboardContext","createContext"],"sources":["context.ts"],"sourcesContent":["import { createContext } from 'react';\nimport { Animated } from 'react-native';\n\nimport type { SharedValue } from 'react-native-reanimated';\n\nexport type AnimatedContext = {\n progress: Animated.Value;\n height: Animated.Value;\n};\nexport type ReanimatedContext = {\n progress: SharedValue<number>;\n height: SharedValue<number>;\n};\nexport type KeyboardAnimationContext = {\n animated: AnimatedContext;\n reanimated: ReanimatedContext;\n};\nconst defaultContext: KeyboardAnimationContext = {\n animated: {\n progress: new Animated.Value(0),\n height: new Animated.Value(0),\n },\n reanimated: {\n progress: { value: 0 },\n height: { value: 0 },\n },\n};\nexport const KeyboardContext = createContext(defaultContext);\n"],"mappings":";;;;;;;AAAA;;AACA;;AAgBA,MAAMA,cAAwC,GAAG;EAC/CC,QAAQ,EAAE;IACRC,QAAQ,EAAE,IAAIC,qBAAA,CAASC,KAAb,CAAmB,CAAnB,CADF;IAERC,MAAM,EAAE,IAAIF,qBAAA,CAASC,KAAb,CAAmB,CAAnB;EAFA,CADqC;EAK/CE,UAAU,EAAE;IACVJ,QAAQ,EAAE;MAAEK,KAAK,EAAE;IAAT,CADA;IAEVF,MAAM,EAAE;MAAEE,KAAK,EAAE;IAAT;EAFE;AALmC,CAAjD;AAUO,MAAMC,eAAe,gBAAG,IAAAC,oBAAA,EAAcT,cAAd,CAAxB"}
1
+ {"version":3,"names":["defaultContext","animated","progress","Animated","Value","height","reanimated","value","setHandlers","KeyboardContext","createContext"],"sources":["context.ts"],"sourcesContent":["import { createContext } from 'react';\nimport { Animated } from 'react-native';\n\nimport type { SharedValue } from 'react-native-reanimated';\nimport type { KeyboardHandlers } from './types';\n\nexport type AnimatedContext = {\n progress: Animated.Value;\n height: Animated.AnimatedMultiplication<number>;\n};\nexport type ReanimatedContext = {\n progress: SharedValue<number>;\n height: SharedValue<number>;\n};\nexport type KeyboardAnimationContext = {\n animated: AnimatedContext;\n reanimated: ReanimatedContext;\n setHandlers: (handlers: KeyboardHandlers) => void;\n};\nconst defaultContext: KeyboardAnimationContext = {\n animated: {\n progress: new Animated.Value(0),\n height: new Animated.Value(0),\n },\n reanimated: {\n progress: { value: 0 },\n height: { value: 0 },\n },\n setHandlers: () => {},\n};\nexport const KeyboardContext = createContext(defaultContext);\n"],"mappings":";;;;;;;AAAA;;AACA;;AAkBA,MAAMA,cAAwC,GAAG;EAC/CC,QAAQ,EAAE;IACRC,QAAQ,EAAE,IAAIC,qBAAA,CAASC,KAAb,CAAmB,CAAnB,CADF;IAERC,MAAM,EAAE,IAAIF,qBAAA,CAASC,KAAb,CAAmB,CAAnB;EAFA,CADqC;EAK/CE,UAAU,EAAE;IACVJ,QAAQ,EAAE;MAAEK,KAAK,EAAE;IAAT,CADA;IAEVF,MAAM,EAAE;MAAEE,KAAK,EAAE;IAAT;EAFE,CALmC;EAS/CC,WAAW,EAAE,MAAM,CAAE;AAT0B,CAAjD;AAWO,MAAMC,eAAe,gBAAG,IAAAC,oBAAA,EAAcV,cAAd,CAAxB"}
@@ -3,7 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.useResizeMode = exports.useReanimatedKeyboardAnimation = exports.useKeyboardAnimation = void 0;
6
+ exports.useGenericKeyboardHandler = useGenericKeyboardHandler;
7
+ exports.useKeyboardAnimation = void 0;
8
+ exports.useKeyboardHandler = useKeyboardHandler;
9
+ exports.useResizeMode = exports.useReanimatedKeyboardAnimation = void 0;
7
10
 
8
11
  var _react = require("react");
9
12
 
@@ -11,6 +14,8 @@ var _context = require("./context");
11
14
 
12
15
  var _native = require("./native");
13
16
 
17
+ var _utils = require("./utils");
18
+
14
19
  const useResizeMode = () => {
15
20
  (0, _react.useEffect)(() => {
16
21
  _native.KeyboardController.setInputMode(_native.AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE);
@@ -36,4 +41,24 @@ const useReanimatedKeyboardAnimation = () => {
36
41
  };
37
42
 
38
43
  exports.useReanimatedKeyboardAnimation = useReanimatedKeyboardAnimation;
44
+
45
+ function useGenericKeyboardHandler(handler, deps) {
46
+ const context = (0, _react.useContext)(_context.KeyboardContext);
47
+ (0, _react.useEffect)(() => {
48
+ const key = (0, _utils.uuid)();
49
+ context.setHandlers({
50
+ [key]: handler
51
+ });
52
+ return () => {
53
+ context.setHandlers({
54
+ [key]: undefined
55
+ });
56
+ };
57
+ }, deps);
58
+ }
59
+
60
+ function useKeyboardHandler(handler, deps) {
61
+ useResizeMode();
62
+ useGenericKeyboardHandler(handler, deps);
63
+ }
39
64
  //# sourceMappingURL=hooks.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useResizeMode","useEffect","KeyboardController","setInputMode","AndroidSoftInputModes","SOFT_INPUT_ADJUST_RESIZE","setDefaultMode","useKeyboardAnimation","context","useContext","KeyboardContext","animated","useReanimatedKeyboardAnimation","reanimated"],"sources":["hooks.ts"],"sourcesContent":["import { useContext, useEffect } from 'react';\n\nimport { AnimatedContext, KeyboardContext, ReanimatedContext } from './context';\nimport { AndroidSoftInputModes, KeyboardController } from './native';\n\nexport const useResizeMode = () => {\n useEffect(() => {\n KeyboardController.setInputMode(\n AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE\n );\n\n return () => KeyboardController.setDefaultMode();\n }, []);\n};\n\nexport const useKeyboardAnimation = (): AnimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.animated;\n};\n\nexport const useReanimatedKeyboardAnimation = (): ReanimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.reanimated;\n};\n"],"mappings":";;;;;;;AAAA;;AAEA;;AACA;;AAEO,MAAMA,aAAa,GAAG,MAAM;EACjC,IAAAC,gBAAA,EAAU,MAAM;IACdC,0BAAA,CAAmBC,YAAnB,CACEC,6BAAA,CAAsBC,wBADxB;;IAIA,OAAO,MAAMH,0BAAA,CAAmBI,cAAnB,EAAb;EACD,CAND,EAMG,EANH;AAOD,CARM;;;;AAUA,MAAMC,oBAAoB,GAAG,MAAuB;EACzDP,aAAa;EACb,MAAMQ,OAAO,GAAG,IAAAC,iBAAA,EAAWC,wBAAX,CAAhB;EAEA,OAAOF,OAAO,CAACG,QAAf;AACD,CALM;;;;AAOA,MAAMC,8BAA8B,GAAG,MAAyB;EACrEZ,aAAa;EACb,MAAMQ,OAAO,GAAG,IAAAC,iBAAA,EAAWC,wBAAX,CAAhB;EAEA,OAAOF,OAAO,CAACK,UAAf;AACD,CALM"}
1
+ {"version":3,"names":["useResizeMode","useEffect","KeyboardController","setInputMode","AndroidSoftInputModes","SOFT_INPUT_ADJUST_RESIZE","setDefaultMode","useKeyboardAnimation","context","useContext","KeyboardContext","animated","useReanimatedKeyboardAnimation","reanimated","useGenericKeyboardHandler","handler","deps","key","uuid","setHandlers","undefined","useKeyboardHandler"],"sources":["hooks.ts"],"sourcesContent":["import { DependencyList, useContext, useEffect } from 'react';\n\nimport { AnimatedContext, KeyboardContext, ReanimatedContext } from './context';\nimport { AndroidSoftInputModes, KeyboardController } from './native';\nimport { uuid } from './utils';\n\nimport type { KeyboardHandler } from './types';\n\nexport const useResizeMode = () => {\n useEffect(() => {\n KeyboardController.setInputMode(\n AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE\n );\n\n return () => KeyboardController.setDefaultMode();\n }, []);\n};\n\nexport const useKeyboardAnimation = (): AnimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.animated;\n};\n\nexport const useReanimatedKeyboardAnimation = (): ReanimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.reanimated;\n};\n\nexport function useGenericKeyboardHandler(\n handler: KeyboardHandler,\n deps?: DependencyList\n) {\n const context = useContext(KeyboardContext);\n\n useEffect(() => {\n const key = uuid();\n\n context.setHandlers({ [key]: handler });\n\n return () => {\n context.setHandlers({ [key]: undefined });\n };\n }, deps);\n}\n\nexport function useKeyboardHandler(\n handler: KeyboardHandler,\n deps?: DependencyList\n) {\n useResizeMode();\n useGenericKeyboardHandler(handler, deps);\n}\n"],"mappings":";;;;;;;;;;AAAA;;AAEA;;AACA;;AACA;;AAIO,MAAMA,aAAa,GAAG,MAAM;EACjC,IAAAC,gBAAA,EAAU,MAAM;IACdC,0BAAA,CAAmBC,YAAnB,CACEC,6BAAA,CAAsBC,wBADxB;;IAIA,OAAO,MAAMH,0BAAA,CAAmBI,cAAnB,EAAb;EACD,CAND,EAMG,EANH;AAOD,CARM;;;;AAUA,MAAMC,oBAAoB,GAAG,MAAuB;EACzDP,aAAa;EACb,MAAMQ,OAAO,GAAG,IAAAC,iBAAA,EAAWC,wBAAX,CAAhB;EAEA,OAAOF,OAAO,CAACG,QAAf;AACD,CALM;;;;AAOA,MAAMC,8BAA8B,GAAG,MAAyB;EACrEZ,aAAa;EACb,MAAMQ,OAAO,GAAG,IAAAC,iBAAA,EAAWC,wBAAX,CAAhB;EAEA,OAAOF,OAAO,CAACK,UAAf;AACD,CALM;;;;AAOA,SAASC,yBAAT,CACLC,OADK,EAELC,IAFK,EAGL;EACA,MAAMR,OAAO,GAAG,IAAAC,iBAAA,EAAWC,wBAAX,CAAhB;EAEA,IAAAT,gBAAA,EAAU,MAAM;IACd,MAAMgB,GAAG,GAAG,IAAAC,WAAA,GAAZ;IAEAV,OAAO,CAACW,WAAR,CAAoB;MAAE,CAACF,GAAD,GAAOF;IAAT,CAApB;IAEA,OAAO,MAAM;MACXP,OAAO,CAACW,WAAR,CAAoB;QAAE,CAACF,GAAD,GAAOG;MAAT,CAApB;IACD,CAFD;EAGD,CARD,EAQGJ,IARH;AASD;;AAEM,SAASK,kBAAT,CACLN,OADK,EAELC,IAFK,EAGL;EACAhB,aAAa;EACbc,yBAAyB,CAACC,OAAD,EAAUC,IAAV,CAAzB;AACD"}
@@ -4,6 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.useAnimatedKeyboardHandler = useAnimatedKeyboardHandler;
7
+ exports.useSharedHandlers = useSharedHandlers;
8
+
9
+ var _react = require("react");
7
10
 
8
11
  var _reactNativeReanimated = require("react-native-reanimated");
9
12
 
@@ -16,12 +19,73 @@ function useAnimatedKeyboardHandler(handlers, dependencies) {
16
19
  'worklet';
17
20
 
18
21
  const {
19
- onKeyboardMove
22
+ onKeyboardMoveStart,
23
+ onKeyboardMove,
24
+ onKeyboardMoveEnd
20
25
  } = handlers;
21
26
 
27
+ if (onKeyboardMoveStart && event.eventName.endsWith('onKeyboardMoveStart')) {
28
+ onKeyboardMoveStart(event, context);
29
+ }
30
+
22
31
  if (onKeyboardMove && event.eventName.endsWith('onKeyboardMove')) {
23
32
  onKeyboardMove(event, context);
24
33
  }
25
- }, ['onKeyboardMove'], doDependenciesDiffer);
34
+
35
+ if (onKeyboardMoveEnd && event.eventName.endsWith('onKeyboardMoveEnd')) {
36
+ onKeyboardMoveEnd(event, context);
37
+ }
38
+ }, ['onKeyboardMoveStart', 'onKeyboardMove', 'onKeyboardMoveEnd'], doDependenciesDiffer);
39
+ }
40
+ /**
41
+ * Hook for storing worklet handlers (objects with keys, where values are worklets).
42
+ * Returns methods for setting handlers and broadcasting events in them.
43
+ *
44
+ * T is a generic that looks like:
45
+ * @example
46
+ * {
47
+ * onEvent: () => {},
48
+ * onEvent2: () => {},
49
+ * }
50
+ */
51
+
52
+
53
+ function useSharedHandlers() {
54
+ const handlers = (0, _reactNativeReanimated.useSharedValue)({});
55
+ const jsHandlers = (0, _react.useRef)({}); // since js -> worklet -> js call is asynchronous, we can not write handlers
56
+ // straight into shared variable (using current shared value as a previous result),
57
+ // since there may be a race condition in a call, and closure may have out-of-dated
58
+ // values. As a result, some of handlers may be not written to "all handlers" object.
59
+ // Below we are writing all handlers to `ref` and afterwards synchronize them with
60
+ // shared value (since `refs` are not referring to actual value in worklets).
61
+ // This approach allow us to update synchronously handlers in js thread (and it assures,
62
+ // that it will have all of them) and then update them in worklet thread (calls are
63
+ // happening in FIFO order, so we will always have actual value).
64
+
65
+ const updateSharedHandlers = () => {
66
+ handlers.value = jsHandlers.current;
67
+ };
68
+
69
+ const setHandlers = (0, _react.useCallback)(handler => {
70
+ jsHandlers.current = { ...jsHandlers.current,
71
+ ...handler
72
+ };
73
+ updateSharedHandlers();
74
+ }, []);
75
+
76
+ const broadcast = (type, event) => {
77
+ 'worklet';
78
+
79
+ Object.keys(handlers.value).forEach(key => {
80
+ var _handlers$value$key, _handlers$value$key$t;
81
+
82
+ return (_handlers$value$key = handlers.value[key]) === null || _handlers$value$key === void 0 ? void 0 : (_handlers$value$key$t = _handlers$value$key[type]) === null || _handlers$value$key$t === void 0 ? void 0 : _handlers$value$key$t.call(_handlers$value$key, event);
83
+ });
84
+ };
85
+
86
+ return {
87
+ setHandlers,
88
+ broadcast
89
+ };
26
90
  }
27
91
  //# sourceMappingURL=internal.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useAnimatedKeyboardHandler","handlers","dependencies","context","doDependenciesDiffer","useHandler","useEvent","event","onKeyboardMove","eventName","endsWith"],"sources":["internal.ts"],"sourcesContent":["import { useEvent, useHandler } from 'react-native-reanimated';\n\nimport type { EventWithName, NativeEvent } from './types';\n\nexport function useAnimatedKeyboardHandler<\n TContext extends Record<string, unknown>\n>(\n handlers: {\n onKeyboardMove?: (e: NativeEvent, context: TContext) => void;\n },\n dependencies?: ReadonlyArray<unknown>\n) {\n const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);\n\n return useEvent(\n (event: EventWithName<NativeEvent>) => {\n 'worklet';\n const { onKeyboardMove } = handlers;\n\n if (onKeyboardMove && event.eventName.endsWith('onKeyboardMove')) {\n onKeyboardMove(event, context);\n }\n },\n ['onKeyboardMove'],\n doDependenciesDiffer\n );\n}\n"],"mappings":";;;;;;;AAAA;;AAIO,SAASA,0BAAT,CAGLC,QAHK,EAMLC,YANK,EAOL;EACA,MAAM;IAAEC,OAAF;IAAWC;EAAX,IAAoC,IAAAC,iCAAA,EAAWJ,QAAX,EAAqBC,YAArB,CAA1C;EAEA,OAAO,IAAAI,+BAAA,EACJC,KAAD,IAAuC;IACrC;;IACA,MAAM;MAAEC;IAAF,IAAqBP,QAA3B;;IAEA,IAAIO,cAAc,IAAID,KAAK,CAACE,SAAN,CAAgBC,QAAhB,CAAyB,gBAAzB,CAAtB,EAAkE;MAChEF,cAAc,CAACD,KAAD,EAAQJ,OAAR,CAAd;IACD;EACF,CARI,EASL,CAAC,gBAAD,CATK,EAULC,oBAVK,CAAP;AAYD"}
1
+ {"version":3,"names":["useAnimatedKeyboardHandler","handlers","dependencies","context","doDependenciesDiffer","useHandler","useEvent","event","onKeyboardMoveStart","onKeyboardMove","onKeyboardMoveEnd","eventName","endsWith","useSharedHandlers","useSharedValue","jsHandlers","useRef","updateSharedHandlers","value","current","setHandlers","useCallback","handler","broadcast","type","Object","keys","forEach","key"],"sources":["internal.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { useEvent, useHandler, useSharedValue } from 'react-native-reanimated';\n\nimport type { EventWithName, Handlers, NativeEvent } from './types';\n\nexport function useAnimatedKeyboardHandler<\n TContext extends Record<string, unknown>\n>(\n handlers: {\n onKeyboardMoveStart?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMove?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMoveEnd?: (e: NativeEvent, context: TContext) => void;\n },\n dependencies?: ReadonlyArray<unknown>\n) {\n const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);\n\n return useEvent(\n (event: EventWithName<NativeEvent>) => {\n 'worklet';\n const { onKeyboardMoveStart, onKeyboardMove, onKeyboardMoveEnd } =\n handlers;\n\n if (\n onKeyboardMoveStart &&\n event.eventName.endsWith('onKeyboardMoveStart')\n ) {\n onKeyboardMoveStart(event, context);\n }\n\n if (onKeyboardMove && event.eventName.endsWith('onKeyboardMove')) {\n onKeyboardMove(event, context);\n }\n\n if (onKeyboardMoveEnd && event.eventName.endsWith('onKeyboardMoveEnd')) {\n onKeyboardMoveEnd(event, context);\n }\n },\n ['onKeyboardMoveStart', 'onKeyboardMove', 'onKeyboardMoveEnd'],\n doDependenciesDiffer\n );\n}\n\n/**\n * Hook for storing worklet handlers (objects with keys, where values are worklets).\n * Returns methods for setting handlers and broadcasting events in them.\n *\n * T is a generic that looks like:\n * @example\n * {\n * onEvent: () => {},\n * onEvent2: () => {},\n * }\n */\nexport function useSharedHandlers<T extends Record<string, Function>>() {\n const handlers = useSharedValue<Handlers<T>>({});\n const jsHandlers = useRef<Handlers<T>>({});\n\n // since js -> worklet -> js call is asynchronous, we can not write handlers\n // straight into shared variable (using current shared value as a previous result),\n // since there may be a race condition in a call, and closure may have out-of-dated\n // values. As a result, some of handlers may be not written to \"all handlers\" object.\n // Below we are writing all handlers to `ref` and afterwards synchronize them with\n // shared value (since `refs` are not referring to actual value in worklets).\n // This approach allow us to update synchronously handlers in js thread (and it assures,\n // that it will have all of them) and then update them in worklet thread (calls are\n // happening in FIFO order, so we will always have actual value).\n const updateSharedHandlers = () => {\n handlers.value = jsHandlers.current;\n };\n const setHandlers = useCallback((handler: Handlers<T>) => {\n jsHandlers.current = {\n ...jsHandlers.current,\n ...handler,\n };\n updateSharedHandlers();\n }, []);\n const broadcast = (type: keyof T, event: NativeEvent) => {\n 'worklet';\n\n Object.keys(handlers.value).forEach((key) =>\n handlers.value[key]?.[type]?.(event)\n );\n };\n\n return { setHandlers, broadcast };\n}\n"],"mappings":";;;;;;;;AAAA;;AACA;;AAIO,SAASA,0BAAT,CAGLC,QAHK,EAQLC,YARK,EASL;EACA,MAAM;IAAEC,OAAF;IAAWC;EAAX,IAAoC,IAAAC,iCAAA,EAAWJ,QAAX,EAAqBC,YAArB,CAA1C;EAEA,OAAO,IAAAI,+BAAA,EACJC,KAAD,IAAuC;IACrC;;IACA,MAAM;MAAEC,mBAAF;MAAuBC,cAAvB;MAAuCC;IAAvC,IACJT,QADF;;IAGA,IACEO,mBAAmB,IACnBD,KAAK,CAACI,SAAN,CAAgBC,QAAhB,CAAyB,qBAAzB,CAFF,EAGE;MACAJ,mBAAmB,CAACD,KAAD,EAAQJ,OAAR,CAAnB;IACD;;IAED,IAAIM,cAAc,IAAIF,KAAK,CAACI,SAAN,CAAgBC,QAAhB,CAAyB,gBAAzB,CAAtB,EAAkE;MAChEH,cAAc,CAACF,KAAD,EAAQJ,OAAR,CAAd;IACD;;IAED,IAAIO,iBAAiB,IAAIH,KAAK,CAACI,SAAN,CAAgBC,QAAhB,CAAyB,mBAAzB,CAAzB,EAAwE;MACtEF,iBAAiB,CAACH,KAAD,EAAQJ,OAAR,CAAjB;IACD;EACF,CApBI,EAqBL,CAAC,qBAAD,EAAwB,gBAAxB,EAA0C,mBAA1C,CArBK,EAsBLC,oBAtBK,CAAP;AAwBD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASS,iBAAT,GAAiE;EACtE,MAAMZ,QAAQ,GAAG,IAAAa,qCAAA,EAA4B,EAA5B,CAAjB;EACA,MAAMC,UAAU,GAAG,IAAAC,aAAA,EAAoB,EAApB,CAAnB,CAFsE,CAItE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EACA,MAAMC,oBAAoB,GAAG,MAAM;IACjChB,QAAQ,CAACiB,KAAT,GAAiBH,UAAU,CAACI,OAA5B;EACD,CAFD;;EAGA,MAAMC,WAAW,GAAG,IAAAC,kBAAA,EAAaC,OAAD,IAA0B;IACxDP,UAAU,CAACI,OAAX,GAAqB,EACnB,GAAGJ,UAAU,CAACI,OADK;MAEnB,GAAGG;IAFgB,CAArB;IAIAL,oBAAoB;EACrB,CANmB,EAMjB,EANiB,CAApB;;EAOA,MAAMM,SAAS,GAAG,CAACC,IAAD,EAAgBjB,KAAhB,KAAuC;IACvD;;IAEAkB,MAAM,CAACC,IAAP,CAAYzB,QAAQ,CAACiB,KAArB,EAA4BS,OAA5B,CAAqCC,GAAD;MAAA;;MAAA,8BAClC3B,QAAQ,CAACiB,KAAT,CAAeU,GAAf,CADkC,iFAClC,oBAAsBJ,IAAtB,CADkC,0DAClC,gDAA8BjB,KAA9B,CADkC;IAAA,CAApC;EAGD,CAND;;EAQA,OAAO;IAAEa,WAAF;IAAeG;EAAf,CAAP;AACD"}