react-native-external-keyboard 0.6.1 → 0.6.2

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.
package/README.md CHANGED
@@ -6,7 +6,7 @@ React Native library for enhanced external keyboard support.
6
6
  - ⚡️ Bridgeless
7
7
 
8
8
  > [!NOTE]
9
- > React Native `0.80.0` includes a fix for `TextInput` focus on Android.
9
+ > React Native `0.80.0` (`0.79.0`) includes a fix for `TextInput` focus on Android.
10
10
  > `TextInput`: Can now focus TextInput with keyboard ([e00028f6bb](https://github.com/facebook/react-native/commit/e00028f6bb6c19de861f9a25f377295755f3671b) by [@joevilches](https://github.com/joevilches))
11
11
  >
12
12
  > This means that there is no need to use the workaround with `KeyboardExtendedInput`, and it is recommended to use the default `TextInput` instead. Additionally, because of changes in `TextInput`, `focusType="press"` for `KeyboardExtendedInput` no longer works on Android.
@@ -21,10 +21,10 @@ Improved keyboard focus control with features like focus order, ordered links, a
21
21
 
22
22
  <details>
23
23
  <summary>More Information</summary>
24
-
24
+
25
25
  Advanced focus order functionality for Android and iOS, plus focus lock!
26
26
 
27
- It can be really challenging to manage focus in React Native, but fortunately, there are tools available to simplify the process.
27
+ It can be really challenging to manage focus in React Native, but fortunately, there are tools available to simplify the process.
28
28
 
29
29
  ## Link Focus Order
30
30
 
@@ -119,7 +119,7 @@ You can find more examples here: [Focus Order via indexes](https://github.com/Ar
119
119
 
120
120
  ## Focus Lock
121
121
 
122
- Finally, you can lock focus to specific directions.
122
+ Finally, you can lock focus to specific directions.
123
123
 
124
124
  ```tsx
125
125
  <Pressable
@@ -134,7 +134,7 @@ Finally, you can lock focus to specific directions.
134
134
  | :-- | :-- | :-- |
135
135
  | lockFocus? | An array of directions to lock focus. | Array of 'left' | 'right' | 'up' | 'down' | 'forward' | 'backward' | 'first' | 'last' |
136
136
 
137
- > [!NOTE]
137
+ > [!NOTE]
138
138
  > `first` and `last` are specific to `iOS`. When focus is blocked for `forward` and `backward` on iOS, it checks for the `last` and `first` elements to focus.
139
139
  </details>
140
140
 
@@ -191,7 +191,7 @@ const KeybardedButton = withKeyboardFocus(Button);
191
191
  </TouchableOpacity>
192
192
  ```
193
193
 
194
- After wrapping a `Pressable` or `Touchable` with `withKeyboardFocus`, you will be able to handle `focus` and `blur` events, control the `tint color`, apply focus and container focus styles, `focus` the component using a `ref`, or configure `autoFocus`.
194
+ After wrapping a `Pressable` or `Touchable` with `withKeyboardFocus`, you will be able to handle `focus` and `blur` events, control the `tint color`, apply focus and container focus styles, `focus` the component using a `ref`, or configure `autoFocus`.
195
195
 
196
196
 
197
197
  Props | Description | Type
@@ -372,7 +372,7 @@ lockFocus? | An array of directions to lock focus. | Array of 'left' \| 'right'
372
372
  The `KeyboardFocusGroup` is a View-based component developed based on the iOS API. It can be used for defining focus groups or setting the `tintColor` globally.
373
373
 
374
374
  ```tsx
375
- <KeyboardFocusGroup
375
+ <KeyboardFocusGroup
376
376
  tintColor="orange">
377
377
  <ScrollView
378
378
  contentContainerStyle={styles.contentContainer}
@@ -381,7 +381,7 @@ The `KeyboardFocusGroup` is a View-based component developed based on the iOS AP
381
381
  ...
382
382
  </ScrollView>
383
383
  </KeyboardFocusGroup>
384
- <KeyboardFocusGroup
384
+ <KeyboardFocusGroup
385
385
  focusStyle={{ backgroundColor: 'green' }}
386
386
  onFocusChange={(e) => console.log('green', e)}
387
387
  groupIdentifier="green"
@@ -515,7 +515,7 @@ You can find more examples here: [Focus Order via indexes](https://github.com/Ar
515
515
 
516
516
  ## Focus Lock
517
517
 
518
- Finally, you can lock focus to specific directions.
518
+ Finally, you can lock focus to specific directions.
519
519
 
520
520
  ```tsx
521
521
  <Pressable
@@ -530,7 +530,7 @@ Finally, you can lock focus to specific directions.
530
530
  | :-- | :-- | :-- |
531
531
  | lockFocus? | An array of directions to lock focus. | Array of 'left' \| 'right' \| 'up' \| 'down' \| 'forward' \| 'backward' \| 'first' \| 'last' |
532
532
 
533
- > [!NOTE]
533
+ > [!NOTE]
534
534
  > `first` and `last` are specific to `iOS`. When focus is blocked for `forward` and `backward` on iOS, it checks for the `last` and `first` elements to focus.
535
535
 
536
536
 
@@ -547,7 +547,7 @@ import { KeyboardExtendedModule } from 'react-native-external-keyboard';
547
547
  KeyboardExtendedModule.setKeyboardFocus(ref); //or A11yModule.setKeyboardFocus(ref);
548
548
  ```
549
549
 
550
- Updated:
550
+ Updated:
551
551
  ```
552
552
  import { KeyboardExtendedPressable, type KeyboardFocus } from 'react-native-external-keyboard';
553
553
  ...
@@ -14,6 +14,7 @@ import com.externalkeyboard.events.EventHelper;
14
14
  import com.externalkeyboard.helper.ReactNativeVersionChecker;
15
15
  import com.externalkeyboard.modules.ExternalKeyboardModule;
16
16
  import com.facebook.react.bridge.ReactContext;
17
+ import com.facebook.react.modules.systeminfo.ReactNativeVersion;
17
18
  import com.facebook.react.views.textinput.ReactEditText;
18
19
 
19
20
  import java.lang.reflect.Field;
@@ -32,9 +33,14 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
32
33
  public boolean getIsFocusByPress() {
33
34
  return focusType == FOCUS_BY_PRESS;
34
35
  }
35
-
36
- private boolean getIs80Version () {
37
- return ReactNativeVersionChecker.isReactNative80OrLater();
36
+ private boolean getIsNativelyFixedVersion () {
37
+ try {
38
+ Object minorValue = ReactNativeVersion.VERSION.getOrDefault("minor", 0);
39
+ int minor = (minorValue instanceof Integer) ? (int) minorValue : 0;
40
+ return minor >= 79;
41
+ } catch (Exception e) {
42
+ return false;
43
+ }
38
44
  }
39
45
 
40
46
  public void setKeyboardFocusable(boolean canBeFocusable) {
@@ -46,8 +52,8 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
46
52
 
47
53
  this.setFocusable(keyboardFocusable);
48
54
  if (this.reactEditText != null) {
49
- boolean is80 = getIs80Version();
50
- this.reactEditText.setFocusable(is80);
55
+ boolean isAlreadyFixed = getIsNativelyFixedVersion();
56
+ this.reactEditText.setFocusable(isAlreadyFixed);
51
57
  }
52
58
  }
53
59
 
@@ -56,8 +62,8 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
56
62
  onAttachListener = new View.OnAttachStateChangeListener() {
57
63
  @Override
58
64
  public void onViewAttachedToWindow(@NonNull View view) {
59
- boolean is80 = getIs80Version();
60
- view.setFocusable(is80);
65
+ boolean isAlreadyFixed = getIsNativelyFixedVersion();
66
+ view.setFocusable(isAlreadyFixed);
61
67
  }
62
68
 
63
69
  @Override
@@ -83,14 +89,14 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
83
89
  public void setEditText(ReactEditText editText) {
84
90
  if (editText != null) {
85
91
  this.reactEditText = editText;
86
- boolean is80 = getIs80Version();
87
- if(is80) {
92
+ boolean isAlreadyFixed = getIsNativelyFixedVersion();
93
+ if(isAlreadyFixed) {
88
94
  this.setFocusable(false);
89
95
  }
90
96
 
91
97
  this.reactEditText.addOnAttachStateChangeListener(getOnAttachListener());
92
98
  if (focusType == FOCUS_BY_PRESS) {
93
- this.reactEditText.setFocusable(is80);
99
+ this.reactEditText.setFocusable(isAlreadyFixed);
94
100
  }
95
101
  OnFocusChangeListener reactListener = this.reactEditText.getOnFocusChangeListener();
96
102
  this.reactEditText.setOnFocusChangeListener((textInput, hasTextEditFocus) -> {
@@ -105,8 +111,8 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
105
111
  ExternalKeyboardModule.setFocusedTextInput(textInput);
106
112
  }
107
113
  if (!hasTextEditFocus) {
108
- this.setFocusable(!is80);
109
- this.reactEditText.setFocusable(is80);
114
+ this.setFocusable(!isAlreadyFixed);
115
+ this.reactEditText.setFocusable(isAlreadyFixed);
110
116
  }
111
117
  });
112
118
  onMultiplyBlurSubmitHandle();
@@ -139,8 +145,8 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
139
145
  this.context = context;
140
146
 
141
147
  if (keyboardFocusable) {
142
- boolean is80 = getIs80Version();
143
- setFocusable(!is80);
148
+ boolean isAlreadyFixed = getIsNativelyFixedVersion();
149
+ setFocusable(!isAlreadyFixed);
144
150
  }
145
151
  }
146
152
 
@@ -166,8 +172,8 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
166
172
  }
167
173
 
168
174
  public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
169
- boolean is80 = getIs80Version();
170
- if(is80) {
175
+ boolean isAlreadyFixed = getIsNativelyFixedVersion();
176
+ if(isAlreadyFixed) {
171
177
  return super.requestFocus(direction, previouslyFocusedRect);
172
178
  }
173
179
  if ((direction == View.FOCUS_FORWARD || direction == View.FOCUS_BACKWARD) && focusType != FOCUS_BY_PRESS) {
@@ -51,38 +51,38 @@
51
51
  if (@available(iOS 15.0, *)) {
52
52
  UIView *focusingView = [_delegate getFocusTargetView];
53
53
  UIFocusEffect *prevEffect = _focusEffect;
54
-
54
+
55
55
  BOOL isHidden = [self isHaloHidden];
56
-
56
+
57
57
  if (isHidden) {
58
58
  _focusEffect = [RNCEKVFocusEffectUtility emptyFocusEffect];
59
59
  }
60
-
60
+
61
61
  BOOL hasHaloSettings = _delegate.haloExpendX || _delegate.haloExpendY ||
62
- _delegate.haloCornerRadius;
62
+ _delegate.haloCornerRadius;
63
63
  BOOL isDifferentBounds =
64
- !CGRectEqualToRect(_prevBounds, focusingView.bounds);
64
+ !CGRectEqualToRect(_prevBounds, focusingView.bounds);
65
65
  BOOL isDifferent = _prevHaloExpendX != _delegate.haloExpendX ||
66
- _prevHaloExpendY != _delegate.haloExpendY ||
67
- _prevHaloCornerRadius != _delegate.haloCornerRadius ||
68
- isDifferentBounds;
69
-
66
+ _prevHaloExpendY != _delegate.haloExpendY ||
67
+ _prevHaloCornerRadius != _delegate.haloCornerRadius ||
68
+ isDifferentBounds;
69
+
70
70
  // ToDo refactor for better halo setup RNCEKV-7, RNCEKV-8
71
71
  if (!isHidden && hasHaloSettings && isDifferent) {
72
72
  _prevHaloExpendX = _delegate.haloExpendX;
73
73
  _prevHaloExpendY = _delegate.haloExpendY;
74
74
  _prevHaloCornerRadius = _delegate.haloCornerRadius;
75
75
  _prevBounds = focusingView.bounds;
76
-
76
+
77
77
  _focusEffect =
78
- [RNCEKVFocusEffectUtility getFocusEffect:focusingView
79
- withExpandedX:_delegate.haloExpendX
80
- withExpandedY:_delegate.haloExpendY
81
- withCornerRadius:_delegate.haloCornerRadius];
78
+ [RNCEKVFocusEffectUtility getFocusEffect:focusingView
79
+ withExpandedX:_delegate.haloExpendX
80
+ withExpandedY:_delegate.haloExpendY
81
+ withCornerRadius:_delegate.haloCornerRadius];
82
82
  }
83
-
83
+
84
84
  if ((_focusEffect == nil && _recycled) || (_focusEffect != nil && prevEffect != _focusEffect &&
85
- focusingView.focusEffect != _focusEffect)) {
85
+ focusingView.focusEffect != _focusEffect)) {
86
86
  _recycled = false;
87
87
  focusingView.focusEffect = _focusEffect;
88
88
  }
@@ -94,24 +94,26 @@
94
94
  return;
95
95
  if (@available(iOS 15.0, *)) {
96
96
  BOOL shouldUpdate = _delegate.haloExpendX || _delegate.haloExpendY ||
97
- _delegate.haloCornerRadius;
97
+ _delegate.haloCornerRadius;
98
98
  if (!shouldUpdate)
99
99
  return;
100
-
100
+
101
101
  UIView *focusingView = [_delegate getFocusTargetView];
102
102
  UIFocusEffect *focusEffect =
103
- [RNCEKVFocusEffectUtility getFocusEffect:focusingView
104
- withExpandedX:_delegate.haloExpendX
105
- withExpandedY:_delegate.haloExpendY
106
- withCornerRadius:_delegate.haloCornerRadius];
107
-
103
+ [RNCEKVFocusEffectUtility getFocusEffect:focusingView
104
+ withExpandedX:_delegate.haloExpendX
105
+ withExpandedY:_delegate.haloExpendY
106
+ withCornerRadius:_delegate.haloCornerRadius];
107
+
108
108
  focusingView.focusEffect = focusEffect;
109
109
  }
110
110
  }
111
111
 
112
112
  - (void) clear {
113
113
  UIView *focusingView = [_delegate getFocusTargetView];
114
- focusingView.focusEffect = nil;
114
+ if (@available(iOS 15.0, *)) {
115
+ focusingView.focusEffect = nil;
116
+ }
115
117
  _focusEffect = nil;
116
118
  _recycled = true;
117
119
  _prevBounds = CGRect();
@@ -0,0 +1,24 @@
1
+ //
2
+ // RCTEnhancedScrollView+RNCEKVExternalKeyboard.mm
3
+ // react-native-external-keyboard
4
+ //
5
+ // Created by Artur Kalach on 09/08/2025.
6
+ //
7
+
8
+
9
+ #ifdef RCT_NEW_ARCH_ENABLED
10
+
11
+ #import "RCTEnhancedScrollView.h"
12
+
13
+ @implementation RCTEnhancedScrollView (RNCEKVExternalKeyboard)
14
+
15
+ - (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments {
16
+ if(self.subviews.count) {
17
+ return @[self.subviews[0]];
18
+ }
19
+ return [super preferredFocusEnvironments];
20
+ }
21
+
22
+ @end
23
+
24
+ #endif
@@ -157,6 +157,10 @@ using namespace facebook::react;
157
157
  _orderRight = nil;
158
158
  _orderUp = nil;
159
159
  _orderDown = nil;
160
+ _orderForward = nil;
161
+ _orderBackward = nil;
162
+ _orderLast = nil;
163
+ _orderFirst = nil;
160
164
  _orderId = nil;
161
165
  _lockFocus = nil;
162
166
  _customGroupId = nil;
@@ -559,6 +563,9 @@ Class<RCTComponentViewProtocol> ExternalKeyboardViewCls(void) {
559
563
 
560
564
  - (void)subviewRecycle: (UIView *)subview {
561
565
  [_gIdDelegate clearSubview: subview];
566
+ if (@available(iOS 15.0, *)) {
567
+ subview.focusEffect = nil;
568
+ }
562
569
  }
563
570
 
564
571
  - (void)willRemoveSubview:(UIView *)subview {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-external-keyboard",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Toolkit for improving physical keyboard support in React Native",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",