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 +273 -12
- package/ios/Delegates/RNCEKVGroupIdentifierDelegate/RNCEKVGroupIdentifierDelegate.h +1 -0
- package/ios/Delegates/RNCEKVGroupIdentifierDelegate/RNCEKVGroupIdentifierDelegate.mm +9 -0
- package/ios/Views/RNCEKVExternalKeyboardView/RNCEKVExternalKeyboardView.mm +12 -2
- package/package.json +1 -1
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
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
-
|
|
362
|
-
-
|
|
363
|
-
-
|
|
364
|
-
-
|
|
365
|
-
-
|
|
366
|
-
-
|
|
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.
|
|
@@ -57,7 +57,7 @@ using namespace facebook::react;
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
- (void)
|
|
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
|
|
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