react-native-external-keyboard 0.6.0 → 0.6.1-rc

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
@@ -12,12 +12,132 @@ React Native library for enhanced external keyboard support.
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.
13
13
 
14
14
 
15
- ## New Release Features
16
- - Added `Keyboard.dismiss` functionality for Android.
17
- - Introduced an iOS-specific component: `KeyboardFocusGroup`, a component for managing the `tintColor`, `focusGroupIdentifier`, and group focus.
18
- - Enhanced `KeyboardExtendedBaseView` with `haloCornerRadius`, `haloExpandX`, and `haloExpandY` properties for customizing the appearance of the `Halo Effect`.
19
- - Enhanced `KeyboardExtendedBaseView` with `onBubbledContextMenuPress`, key press functionality has been also enhanced. Key presses can be listened to for a group of components, screens, or pages.
20
- - Added the `ignoreGroupFocusHint` prop to `KeyboardExtendedBaseView` to support key press listening without focusing the container.
15
+ ## New Release: Focus Lock and Focus Order
16
+ Improved keyboard focus control with features like focus order, ordered links, and focus lock.
17
+
18
+ |Android| iOS|
19
+ |-|-|
20
+ | <image alt="Android Focus Order Example" src="https://github.com/user-attachments/assets/8bae353e-cf4b-41f7-8796-fd1cceae5df5" height="400" />| <image alt="iOS Focus Order Example" src="https://github.com/user-attachments/assets/51850cc6-9573-4ccb-b69c-14deefbb4b65" height="400"/> |
21
+
22
+ <details>
23
+ <summary>More Information</summary>
24
+
25
+ Advanced focus order functionality for Android and iOS, plus focus lock!
26
+
27
+ It can be really challenging to manage focus in React Native, but fortunately, there are tools available to simplify the process.
28
+
29
+ ## Link Focus Order
30
+
31
+ `Linking` components could be the most logical way to define focus order. By using properties such as `orderId` and `orderBackward`, `orderForward`, `orderLeft`, `orderRight`, `orderUp`, and `orderDown`, you can customize the focus order according to your needs.
32
+
33
+ ```tsx
34
+ <View>
35
+ <Pressable
36
+ onPress={onPress}
37
+ orderId="0_0"
38
+ orderForward="0_2"
39
+ >
40
+ <Text>1</Text>
41
+ </Pressable>
42
+ <Pressable
43
+ onPress={onPress}
44
+ orderId="0_2"
45
+ orderBackward="0_1"
46
+ >
47
+ <Text>3</Text>
48
+ </Pressable>
49
+ <Pressable
50
+ onPress={onPress}
51
+ orderId="0_1"
52
+ orderForward="0_2"
53
+ orderBackward="0_0"
54
+ >
55
+ <Text>2</Text>
56
+ </Pressable>
57
+ </View>
58
+ ```
59
+
60
+ You can find more examples here: [Focus Link Order](https://github.com/ArturKalach/react-native-external-keyboard/blob/release/0.6.0-rc/example/src/components/FocusOrderExample/FocusLinkOrder.tsx), [DPad Order](https://github.com/ArturKalach/react-native-external-keyboard/blob/release/0.6.0-rc/example/src/components/FocusOrderExample/FocusDPadOrder.tsx)
61
+
62
+ | Props | Description | Type |
63
+ | :-- | :-- | :-- |
64
+ | orderId? | A unique ID used for link target identification. | `string` |
65
+ | orderBackward? | ID of the target for backward navigation with "Tab + Shift". | `string` |
66
+ | orderForward? | ID of the target for forward navigation with "Tab". | `string` |
67
+ | orderLeft? | ID of the target for navigation to the left. | `string` |
68
+ | orderRight? | ID of the target for navigation to the right. | `string` |
69
+ | orderUp? | ID of the target for navigation upward. | `string` |
70
+ | orderDown? | ID of the target for navigation downward. | `string` |
71
+
72
+ ## Indexes Focus Order
73
+
74
+ Linking is one of the best ways to set up focus order. However, there may be cases where you need to define the order of multiple elements, such as groups. As an alternative solution, you can use Indexes.
75
+
76
+ ```tsx
77
+ <KeyboardOrderFocusGroup>
78
+ <View>
79
+ <Pressable
80
+ onPress={onPress}
81
+ orderIndex={0}
82
+ >
83
+ <Text>First</Text>
84
+ </Pressable>
85
+ <Pressable
86
+ onPress={onPress}
87
+ orderIndex={2}
88
+ >
89
+ <Text>Third</Text>
90
+ </Pressable>
91
+ <Pressable
92
+ onPress={onPress}
93
+ orderIndex={1}
94
+ >
95
+ <Text>Second</Text>
96
+ </Pressable>
97
+ </View>
98
+ </KeyboardOrderFocusGroup>
99
+ ```
100
+ Indexing requres `orderGroup` param for proper order set, you can use `KeyboardOrderFocusGroup` or provide `orderGroup` to the component.
101
+
102
+ ```tsx
103
+ <Pressable
104
+ orderGroup="main"
105
+ onPress={onPress}
106
+ orderIndex={2}
107
+ >
108
+ <Text>Back</Text>
109
+ </Pressable>
110
+ ```
111
+
112
+ | Props | Description | Type |
113
+ | :-- | :-- | :-- |
114
+ | orderGroup? | The name of the group containing ordered elements. | `string` |
115
+ | orderIndex? | The order index of the element within the group. | `number` |
116
+
117
+
118
+ You can find more examples here: [Focus Order via indexes](https://github.com/ArturKalach/react-native-external-keyboard/blob/release/0.6.0-rc/example/src/components/FocusOrderExample/FocusOrder.tsx)
119
+
120
+ ## Focus Lock
121
+
122
+ Finally, you can lock focus to specific directions.
123
+
124
+ ```tsx
125
+ <Pressable
126
+ lockFocus={['down', 'right']}
127
+ >
128
+ <Text>Lock Example</Text>
129
+ </Pressable>
130
+ ```
131
+
132
+
133
+ | Props | Description | Type |
134
+ | :-- | :-- | :-- |
135
+ | lockFocus? | An array of directions to lock focus. | Array of 'left' | 'right' | 'up' | 'down' | 'forward' | 'backward' | 'first' | 'last' |
136
+
137
+ > [!NOTE]
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
+ </details>
140
+
21
141
 
22
142
  iOS | Android
23
143
  -- | --
@@ -29,6 +149,7 @@ iOS | Android
29
149
  - Key press event handling.
30
150
  - Focus management for `TextInput` and `Pressable` components.
31
151
  - Customization of the `Halo Effect` and `tintColor` for iOS.
152
+ - Keyboard focus order.
32
153
 
33
154
  ## Installation
34
155
 
@@ -104,6 +225,14 @@ enableA11yFocus?: | Can be used to move the screen reader focus within the keybo
104
225
  screenAutoA11yFocus?: | Enables screen reader auto-focus functionality. | `boolean \| undefined`
105
226
  `screenAutoA11yFocusDelay?:` | **Android only:** Delay for screen reader autofocus. On Android, focus can only be applied after the component has rendered, which may take 300–500 milliseconds. | `number \| undefined`, default: 300
106
227
  `exposeMethods?:` | List of exposed view methods | `string[] \| undefined`, by default the following methods are exposed: `'blur', 'measure', 'measureInWindow', 'measureLayout', and 'setNativeProps'`.
228
+ orderId? | A unique ID used for link target identification. | `string`
229
+ orderBackward? | ID of the target for backward navigation with "Tab + Shift". | `string`
230
+ orderForward? | ID of the target for forward navigation with "Tab". | `string`
231
+ orderLeft? | ID of the target for navigation to the left. | `string`
232
+ orderRight? | ID of the target for navigation to the right. | `string`
233
+ orderUp? | ID of the target for navigation upward. | `string`
234
+ orderDown? | ID of the target for navigation downward. | `string`
235
+ lockFocus? | An array of directions to lock focus. | Array of 'left' \| 'right' \| 'up' \| 'down' \| 'forward' \| 'backward' \| 'first' \| 'last'
107
236
  ...rest | Remaining component props  | `Type of Component`
108
237
 
109
238
 
@@ -155,6 +284,14 @@ enableA11yFocus?: | Can be used to move the screen reader focus within the keybo
155
284
  screenAutoA11yFocus?: | Enables screen reader auto-focus functionality. | `boolean \| undefined`
156
285
  `screenAutoA11yFocusDelay?:` | **Android only:** Delay for screen reader autofocus. On Android, focus can only be applied after the component has rendered, which may take 300–500 milliseconds. | `number \| undefined`, default: 300
157
286
  `exposeMethods?:` | List of exposed view methods | `string[] \| undefined`, by default the following methods are exposed: `'blur', 'measure', 'measureInWindow', 'measureLayout', and 'setNativeProps'`.
287
+ orderId? | A unique ID used for link target identification. | `string`
288
+ orderBackward? | ID of the target for backward navigation with "Tab + Shift". | `string`
289
+ orderForward? | ID of the target for forward navigation with "Tab". | `string`
290
+ orderLeft? | ID of the target for navigation to the left. | `string`
291
+ orderRight? | ID of the target for navigation to the right. | `string`
292
+ orderUp? | ID of the target for navigation upward. | `string`
293
+ orderDown? | ID of the target for navigation downward. | `string`
294
+ lockFocus? | An array of directions to lock focus. | Array of 'left' \| 'right' \| 'up' \| 'down' \| 'forward' \| 'backward' \| 'first' \| 'last'
158
295
  ...rest | Remaining View props  | `View`
159
296
 
160
297
 
@@ -221,6 +358,14 @@ haloEffect | Enables halo effect on focus (iOS only) | `boolean \| undefined`
221
358
  autoFocus | Indicates if the component should automatically gain focus | `boolean \| undefined`
222
359
  tintColor | Color used for tinting the component | `string`
223
360
  ref->focus | Command to programmatically focus the component | () => void;
361
+ orderId? | A unique ID used for link target identification. | `string`
362
+ orderBackward? | ID of the target for backward navigation with "Tab + Shift". | `string`
363
+ orderForward? | ID of the target for forward navigation with "Tab". | `string`
364
+ orderLeft? | ID of the target for navigation to the left. | `string`
365
+ orderRight? | ID of the target for navigation to the right. | `string`
366
+ orderUp? | ID of the target for navigation upward. | `string`
367
+ orderDown? | ID of the target for navigation downward. | `string`
368
+ lockFocus? | An array of directions to lock focus. | Array of 'left' \| 'right' \| 'up' \| 'down' \| 'forward' \| 'backward' \| 'first' \| 'last'
224
369
  ...rest | Remaining View props | `View`
225
370
 
226
371
  ### KeyboardFocusGroup
@@ -275,6 +420,120 @@ import { Keyboard } from 'react-native-external-keyboard';
275
420
 
276
421
  This is needed for hiding the soft keyboard using a hardware keyboard. Additionally, the soft keyboard can be hidden from the settings or by pressing `Alt + K`.
277
422
 
423
+ ## Focus order features
424
+
425
+ ## Link Focus Order
426
+
427
+ `Linking` components could be the most logical way to define focus order. By using properties such as `orderId` and `orderBackward`, `orderForward`, `orderLeft`, `orderRight`, `orderUp`, and `orderDown`, you can customize the focus order according to your needs.
428
+
429
+ ```tsx
430
+ <View>
431
+ <Pressable
432
+ onPress={onPress}
433
+ orderId="0_0"
434
+ orderForward="0_2"
435
+ >
436
+ <Text>1</Text>
437
+ </Pressable>
438
+ <Pressable
439
+ onPress={onPress}
440
+ orderId="0_2"
441
+ orderBackward="0_1"
442
+ >
443
+ <Text>3</Text>
444
+ </Pressable>
445
+ <Pressable
446
+ onPress={onPress}
447
+ orderId="0_1"
448
+ orderForward="0_2"
449
+ orderBackward="0_0"
450
+ >
451
+ <Text>2</Text>
452
+ </Pressable>
453
+ </View>
454
+ ```
455
+
456
+ You can find more examples here: [Focus Link Order](https://github.com/ArturKalach/react-native-external-keyboard/blob/release/0.6.0-rc/example/src/components/FocusOrderExample/FocusLinkOrder.tsx), [DPad Order](https://github.com/ArturKalach/react-native-external-keyboard/blob/release/0.6.0-rc/example/src/components/FocusOrderExample/FocusDPadOrder.tsx)
457
+
458
+ | Props | Description | Type |
459
+ | :-- | :-- | :-- |
460
+ | orderId? | A unique ID used for link target identification. | `string` |
461
+ | orderBackward? | ID of the target for backward navigation with "Tab + Shift". | `string` |
462
+ | orderForward? | ID of the target for forward navigation with "Tab". | `string` |
463
+ | orderLeft? | ID of the target for navigation to the left. | `string` |
464
+ | orderRight? | ID of the target for navigation to the right. | `string` |
465
+ | orderUp? | ID of the target for navigation upward. | `string` |
466
+ | orderDown? | ID of the target for navigation downward. | `string` |
467
+
468
+ ## Indexes Focus Order
469
+
470
+ Linking is one of the best ways to set up focus order. However, there may be cases where you need to define the order of multiple elements, such as groups. As an alternative solution, you can use Indexes.
471
+
472
+ ```tsx
473
+ <KeyboardOrderFocusGroup>
474
+ <View>
475
+ <Pressable
476
+ onPress={onPress}
477
+ orderIndex={0}
478
+ >
479
+ <Text>First</Text>
480
+ </Pressable>
481
+ <Pressable
482
+ onPress={onPress}
483
+ orderIndex={2}
484
+ >
485
+ <Text>Third</Text>
486
+ </Pressable>
487
+ <Pressable
488
+ onPress={onPress}
489
+ orderIndex={1}
490
+ >
491
+ <Text>Second</Text>
492
+ </Pressable>
493
+ </View>
494
+ </KeyboardOrderFocusGroup>
495
+ ```
496
+ Indexing requres `orderGroup` param for proper order set, you can use `KeyboardOrderFocusGroup` or provide `orderGroup` to the component.
497
+
498
+ ```tsx
499
+ <Pressable
500
+ orderGroup="main"
501
+ onPress={onPress}
502
+ orderIndex={2}
503
+ >
504
+ <Text>Back</Text>
505
+ </Pressable>
506
+ ```
507
+
508
+ | Props | Description | Type |
509
+ | :-- | :-- | :-- |
510
+ | orderGroup? | The name of the group containing ordered elements. | `string` |
511
+ | orderIndex? | The order index of the element within the group. | `number` |
512
+
513
+
514
+ You can find more examples here: [Focus Order via indexes](https://github.com/ArturKalach/react-native-external-keyboard/blob/release/0.6.0-rc/example/src/components/FocusOrderExample/FocusOrder.tsx)
515
+
516
+ ## Focus Lock
517
+
518
+ Finally, you can lock focus to specific directions.
519
+
520
+ ```tsx
521
+ <Pressable
522
+ lockFocus={['down', 'right']}
523
+ >
524
+ <Text>Lock Example</Text>
525
+ </Pressable>
526
+ ```
527
+
528
+
529
+ | Props | Description | Type |
530
+ | :-- | :-- | :-- |
531
+ | lockFocus? | An array of directions to lock focus. | Array of 'left' \| 'right' \| 'up' \| 'down' \| 'forward' \| 'backward' \| 'first' \| 'last' |
532
+
533
+ > [!NOTE]
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
+
536
+
278
537
  # Migration 0.3.x to 0.4.0
279
538
 
280
539
  ## Module (A11yModule, KeyboardExtendedModule)
@@ -358,12 +617,14 @@ export type OnKeyPress = NativeSyntheticEvent<{
358
617
  ```
359
618
 
360
619
  ## Roadmap
361
- - Update `onPress` and `onLongPress` for `withKeyboardFocus`
362
- - Add functionality to control keyboard focus order.
363
- - Verify and update `focusable` and `disabled` states for iOS and Android.
364
- - Update `Readme.md`.
365
- - Create the documentation.
366
- - Perfomance optimization
620
+ - [ ] Refactor and Performance optimization
621
+ - [ ] Update `focusGroupIdentifier` and implement `KeyboardNavigationCluster` functionality
622
+ - [ ] Update `onPress` and `onLongPress` for `withKeyboardFocus`
623
+ - [x] Add functionality to control keyboard focus order.
624
+ - [ ] Verify and update `focusable` and `disabled` states for iOS and Android.
625
+ - [ ] Update `Readme.md`.
626
+ - [ ] Create the documentation.
627
+
367
628
 
368
629
  ## Contributing
369
630
  Any type of contribution is highly appreciated. Feel free to create PRs, raise issues, or share ideas.
@@ -18,6 +18,7 @@
18
18
  - (NSString*_Nonnull) getFocusGroupIdentifier;
19
19
  - (void)updateGroupIdentifier;
20
20
  - (void)clear;
21
+ - (void)clearSubview: (UIView*_Nullable)view;
21
22
  @end
22
23
 
23
24
 
@@ -59,4 +59,13 @@
59
59
  }
60
60
  }
61
61
  }
62
+
63
+ - (void)clearSubview: (UIView*_Nullable)view {
64
+ if (@available(iOS 14.0, *)) {
65
+ _tagId = nil;
66
+ if(view.focusGroupIdentifier != nil) {
67
+ view.focusGroupIdentifier = nil;
68
+ }
69
+ }
70
+ }
62
71
  @end
@@ -57,7 +57,7 @@ using namespace facebook::react;
57
57
  }
58
58
  }
59
59
 
60
- - (void)unkink{
60
+ - (void)unlink{
61
61
  if(_orderPosition != nil && _orderGroup != nil && _isLinked) {
62
62
  [[RNCEKVOrderLinking sharedInstance] remove:_orderPosition withOrderKey: _orderGroup];
63
63
  }
@@ -85,7 +85,7 @@ using namespace facebook::react;
85
85
 
86
86
  - (void)onDetached
87
87
  {
88
- [self unkink];
88
+ [self unlink];
89
89
  }
90
90
 
91
91
 
@@ -458,6 +458,7 @@ Class<RCTComponentViewProtocol> ExternalKeyboardViewCls(void) {
458
458
 
459
459
  #endif
460
460
 
461
+
461
462
  - (void)a11yFocus {
462
463
  if (!_enableA11yFocus)
463
464
  return;
@@ -556,6 +557,15 @@ Class<RCTComponentViewProtocol> ExternalKeyboardViewCls(void) {
556
557
  // [self setupLayout];
557
558
  }
558
559
 
560
+ - (void)subviewRecycle: (UIView *)subview {
561
+ [_gIdDelegate clearSubview: subview];
562
+ }
563
+
564
+ - (void)willRemoveSubview:(UIView *)subview {
565
+ [super willRemoveSubview:subview];
566
+ [self subviewRecycle: subview];
567
+ }
568
+
559
569
  - (void)viewControllerChanged:(NSNotification *)notification {
560
570
  UIViewController *viewController = notification.object;
561
571
  if (self.autoFocus && !_isAttachedToController) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-external-keyboard",
3
- "version": "0.6.0",
3
+ "version": "0.6.1-rc",
4
4
  "description": "Toolkit for improving physical keyboard support in React Native",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",