Skip to content

Commit 80b4385

Browse files
authored
Fix/handle native events (#105)
* Initial modifications to handle native events * fix: handle native events with shouldUseNativeEvents flag implemented * Version bump, changelog * Version bump & changelog modified * Merge conflict fixed. Linter applied
1 parent f087670 commit 80b4385

4 files changed

Lines changed: 64 additions & 31 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
# [2.1.0]
8+
## Added
9+
- new `init` config option `shouldUseNativeEvents` that enables the use of native events for triggering actions, such as clicks or key presses.
10+
- new `init` config option `rtl` that changes focus behavior for layouts in right-to-left (RTL) languages such as Arabic and Hebrew.
11+
712
# [2.0.2]
813
## Added
914
- Console warning when passing an empty `ref` to `useFocusable`

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ Also consider `role` and `aria-label` attributes. But that depends on the applic
260260

261261
The flag is ignored if `nativeMode` is set.
262262

263+
### `shouldUseNativeEvents`: boolean (default: false)
264+
This flag, when set to true, enables the use of native events for triggering actions, such as clicks or key presses. For instance, the onClick method will be triggered while pressing the enterKey, as well as cliicking the element itself. It is particularly beneficial for enhancing the accessibility of web applications. When shouldUseNativeEvents is active, the underlying accessible DOM node becomes the focus of the event.
265+
263266
##### `rtl`: boolean (default: false)
264267
This flag changes focus behavior for layouts in right-to-left (RTL) languages such as Arabic and Hebrew.
265268

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@noriginmedia/norigin-spatial-navigation",
3-
"version": "2.0.2",
3+
"version": "2.1.0",
44
"description": "React hooks based Spatial Navigation solution",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/SpatialNavigation.ts

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,18 @@ export type BackwardsCompatibleKeyMap = {
139139

140140
export type KeyMap = { [index: string]: (string | number)[] };
141141

142-
const getChildClosestToOrigin = (children: FocusableComponent[], writingDirection: WritingDirection) => {
143-
const comparator = writingDirection === WritingDirection.LTR
144-
? (({ layout }: FocusableComponent) => Math.abs(layout.left) + Math.abs(layout.top))
145-
: (({ layout }: FocusableComponent) => Math.abs(window.innerWidth - layout.right) + Math.abs(layout.top));
146-
147-
const childrenClosestToOrigin = sortBy(
148-
children,
149-
comparator,
150-
);
142+
const getChildClosestToOrigin = (
143+
children: FocusableComponent[],
144+
writingDirection: WritingDirection
145+
) => {
146+
const comparator =
147+
writingDirection === WritingDirection.LTR
148+
? ({ layout }: FocusableComponent) =>
149+
Math.abs(layout.left) + Math.abs(layout.top)
150+
: ({ layout }: FocusableComponent) =>
151+
Math.abs(window.innerWidth - layout.right) + Math.abs(layout.top);
152+
153+
const childrenClosestToOrigin = sortBy(children, comparator);
151154

152155
return first(childrenClosestToOrigin);
153156
};
@@ -178,6 +181,8 @@ class SpatialNavigationService {
178181

179182
private shouldFocusDOMNode: boolean;
180183

184+
private shouldUseNativeEvents: boolean;
185+
181186
/**
182187
* This collection contains focus keys of the elements that are having a child focused
183188
* Might be handy for styling of certain parent components if their child is focused.
@@ -244,27 +249,27 @@ class SpatialNavigationService {
244249
isIncremental: boolean,
245250
isSibling: boolean,
246251
layout: FocusableComponentLayout,
247-
writingDirection: WritingDirection,
252+
writingDirection: WritingDirection
248253
) {
249254
const itemStart = isVertical
250255
? layout.top
251256
: writingDirection === WritingDirection.LTR
252-
? layout.left
253-
: layout.right;
257+
? layout.left
258+
: layout.right;
254259

255260
const itemEnd = isVertical
256261
? layout.bottom
257262
: writingDirection === WritingDirection.LTR
258-
? layout.right
259-
: layout.left;
263+
? layout.right
264+
: layout.left;
260265

261266
return isIncremental
262267
? isSibling
263268
? itemStart
264269
: itemEnd
265270
: isSibling
266-
? itemEnd
267-
: itemStart;
271+
? itemEnd
272+
: itemStart;
268273
}
269274

270275
/**
@@ -545,6 +550,7 @@ class SpatialNavigationService {
545550
this.throttleKeypresses = false;
546551
this.useGetBoundingClientRect = false;
547552
this.shouldFocusDOMNode = false;
553+
this.shouldUseNativeEvents = false;
548554
this.writingDirection = WritingDirection.LTR;
549555

550556
this.pressedKeys = {};
@@ -591,6 +597,7 @@ class SpatialNavigationService {
591597
throttleKeypresses = false,
592598
useGetBoundingClientRect = false,
593599
shouldFocusDOMNode = false,
600+
shouldUseNativeEvents = false,
594601
rtl = false
595602
} = {}) {
596603
if (!this.enabled) {
@@ -599,6 +606,7 @@ class SpatialNavigationService {
599606
this.throttleKeypresses = throttleKeypresses;
600607
this.useGetBoundingClientRect = useGetBoundingClientRect;
601608
this.shouldFocusDOMNode = shouldFocusDOMNode && !nativeMode;
609+
this.shouldUseNativeEvents = shouldUseNativeEvents;
602610
this.writingDirection = rtl ? WritingDirection.RTL : WritingDirection.LTR;
603611

604612
this.debug = debug;
@@ -696,8 +704,10 @@ class SpatialNavigationService {
696704
? this.pressedKeys[eventType] + 1
697705
: 1;
698706

699-
event.preventDefault();
700-
event.stopPropagation();
707+
if (!this.shouldUseNativeEvents) {
708+
event.preventDefault();
709+
event.stopPropagation();
710+
}
701711

702712
const keysDetails = {
703713
pressedKeys: this.pressedKeys
@@ -896,7 +906,10 @@ class SpatialNavigationService {
896906
const isVerticalDirection =
897907
direction === DIRECTION_DOWN || direction === DIRECTION_UP;
898908
const isIncrementalDirection =
899-
direction === DIRECTION_DOWN || (this.writingDirection === WritingDirection.LTR ? direction === DIRECTION_RIGHT : direction === DIRECTION_LEFT);
909+
direction === DIRECTION_DOWN ||
910+
(this.writingDirection === WritingDirection.LTR
911+
? direction === DIRECTION_RIGHT
912+
: direction === DIRECTION_LEFT);
900913

901914
this.log('smartNavigate', 'direction', direction);
902915
this.log('smartNavigate', 'fromParentFocusKey', fromParentFocusKey);
@@ -939,7 +952,7 @@ class SpatialNavigationService {
939952
isIncrementalDirection,
940953
false,
941954
layout,
942-
this.writingDirection,
955+
this.writingDirection
943956
);
944957

945958
/**
@@ -957,21 +970,20 @@ class SpatialNavigationService {
957970
isIncrementalDirection,
958971
true,
959972
component.layout,
960-
this.writingDirection,
973+
this.writingDirection
961974
);
962975

963976
return isVerticalDirection
964977
? isIncrementalDirection
965978
? siblingCutoffCoordinate >= currentCutoffCoordinate // vertical next
966979
: siblingCutoffCoordinate <= currentCutoffCoordinate // vertical previous
967980
: this.writingDirection === WritingDirection.LTR
968-
? isIncrementalDirection
969-
? siblingCutoffCoordinate >= currentCutoffCoordinate // horizontal LTR next
970-
: siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal LTR previous
971-
: isIncrementalDirection
972-
? siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal RTL next
973-
: siblingCutoffCoordinate >= currentCutoffCoordinate // horizontal RTL previous
974-
;
981+
? isIncrementalDirection
982+
? siblingCutoffCoordinate >= currentCutoffCoordinate // horizontal LTR next
983+
: siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal LTR previous
984+
: isIncrementalDirection
985+
? siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal RTL next
986+
: siblingCutoffCoordinate >= currentCutoffCoordinate; // horizontal RTL previous
975987
}
976988

977989
return false;
@@ -1087,7 +1099,17 @@ class SpatialNavigationService {
10871099
*/
10881100
const sortedForceFocusableComponents = this.sortSiblingsByPriority(
10891101
forceFocusableComponents,
1090-
{ x: 0, y: 0, width: 0, height: 0, left: 0, top: 0, right: 0, bottom: 0, node: null },
1102+
{
1103+
x: 0,
1104+
y: 0,
1105+
width: 0,
1106+
height: 0,
1107+
left: 0,
1108+
top: 0,
1109+
right: 0,
1110+
bottom: 0,
1111+
node: null
1112+
},
10911113
'down',
10921114
ROOT_FOCUS_KEY
10931115
);
@@ -1167,7 +1189,10 @@ class SpatialNavigationService {
11671189
* Otherwise, trying to focus something by coordinates
11681190
*/
11691191
children.forEach((component) => this.updateLayout(component.focusKey));
1170-
const { focusKey: childKey } = getChildClosestToOrigin(children, this.writingDirection);
1192+
const { focusKey: childKey } = getChildClosestToOrigin(
1193+
children,
1194+
this.writingDirection
1195+
);
11711196

11721197
this.log('getNextFocusKey', 'childKey will be focused', childKey);
11731198

0 commit comments

Comments
 (0)