Skip to content

Commit

Permalink
Fix/handle native events (#105)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Braggiouy authored Nov 15, 2023
1 parent f087670 commit 80b4385
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 31 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

# [2.1.0]
## Added
- new `init` config option `shouldUseNativeEvents` that enables the use of native events for triggering actions, such as clicks or key presses.
- new `init` config option `rtl` that changes focus behavior for layouts in right-to-left (RTL) languages such as Arabic and Hebrew.

# [2.0.2]
## Added
- Console warning when passing an empty `ref` to `useFocusable`
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ Also consider `role` and `aria-label` attributes. But that depends on the applic

The flag is ignored if `nativeMode` is set.

### `shouldUseNativeEvents`: boolean (default: false)
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.

##### `rtl`: boolean (default: false)
This flag changes focus behavior for layouts in right-to-left (RTL) languages such as Arabic and Hebrew.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@noriginmedia/norigin-spatial-navigation",
"version": "2.0.2",
"version": "2.1.0",
"description": "React hooks based Spatial Navigation solution",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
85 changes: 55 additions & 30 deletions src/SpatialNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,18 @@ export type BackwardsCompatibleKeyMap = {

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

const getChildClosestToOrigin = (children: FocusableComponent[], writingDirection: WritingDirection) => {
const comparator = writingDirection === WritingDirection.LTR
? (({ layout }: FocusableComponent) => Math.abs(layout.left) + Math.abs(layout.top))
: (({ layout }: FocusableComponent) => Math.abs(window.innerWidth - layout.right) + Math.abs(layout.top));

const childrenClosestToOrigin = sortBy(
children,
comparator,
);
const getChildClosestToOrigin = (
children: FocusableComponent[],
writingDirection: WritingDirection
) => {
const comparator =
writingDirection === WritingDirection.LTR
? ({ layout }: FocusableComponent) =>
Math.abs(layout.left) + Math.abs(layout.top)
: ({ layout }: FocusableComponent) =>
Math.abs(window.innerWidth - layout.right) + Math.abs(layout.top);

const childrenClosestToOrigin = sortBy(children, comparator);

return first(childrenClosestToOrigin);
};
Expand Down Expand Up @@ -178,6 +181,8 @@ class SpatialNavigationService {

private shouldFocusDOMNode: boolean;

private shouldUseNativeEvents: boolean;

/**
* This collection contains focus keys of the elements that are having a child focused
* Might be handy for styling of certain parent components if their child is focused.
Expand Down Expand Up @@ -244,27 +249,27 @@ class SpatialNavigationService {
isIncremental: boolean,
isSibling: boolean,
layout: FocusableComponentLayout,
writingDirection: WritingDirection,
writingDirection: WritingDirection
) {
const itemStart = isVertical
? layout.top
: writingDirection === WritingDirection.LTR
? layout.left
: layout.right;
? layout.left
: layout.right;

const itemEnd = isVertical
? layout.bottom
: writingDirection === WritingDirection.LTR
? layout.right
: layout.left;
? layout.right
: layout.left;

return isIncremental
? isSibling
? itemStart
: itemEnd
: isSibling
? itemEnd
: itemStart;
? itemEnd
: itemStart;
}

/**
Expand Down Expand Up @@ -545,6 +550,7 @@ class SpatialNavigationService {
this.throttleKeypresses = false;
this.useGetBoundingClientRect = false;
this.shouldFocusDOMNode = false;
this.shouldUseNativeEvents = false;
this.writingDirection = WritingDirection.LTR;

this.pressedKeys = {};
Expand Down Expand Up @@ -591,6 +597,7 @@ class SpatialNavigationService {
throttleKeypresses = false,
useGetBoundingClientRect = false,
shouldFocusDOMNode = false,
shouldUseNativeEvents = false,
rtl = false
} = {}) {
if (!this.enabled) {
Expand All @@ -599,6 +606,7 @@ class SpatialNavigationService {
this.throttleKeypresses = throttleKeypresses;
this.useGetBoundingClientRect = useGetBoundingClientRect;
this.shouldFocusDOMNode = shouldFocusDOMNode && !nativeMode;
this.shouldUseNativeEvents = shouldUseNativeEvents;
this.writingDirection = rtl ? WritingDirection.RTL : WritingDirection.LTR;

this.debug = debug;
Expand Down Expand Up @@ -696,8 +704,10 @@ class SpatialNavigationService {
? this.pressedKeys[eventType] + 1
: 1;

event.preventDefault();
event.stopPropagation();
if (!this.shouldUseNativeEvents) {
event.preventDefault();
event.stopPropagation();
}

const keysDetails = {
pressedKeys: this.pressedKeys
Expand Down Expand Up @@ -896,7 +906,10 @@ class SpatialNavigationService {
const isVerticalDirection =
direction === DIRECTION_DOWN || direction === DIRECTION_UP;
const isIncrementalDirection =
direction === DIRECTION_DOWN || (this.writingDirection === WritingDirection.LTR ? direction === DIRECTION_RIGHT : direction === DIRECTION_LEFT);
direction === DIRECTION_DOWN ||
(this.writingDirection === WritingDirection.LTR
? direction === DIRECTION_RIGHT
: direction === DIRECTION_LEFT);

this.log('smartNavigate', 'direction', direction);
this.log('smartNavigate', 'fromParentFocusKey', fromParentFocusKey);
Expand Down Expand Up @@ -939,7 +952,7 @@ class SpatialNavigationService {
isIncrementalDirection,
false,
layout,
this.writingDirection,
this.writingDirection
);

/**
Expand All @@ -957,21 +970,20 @@ class SpatialNavigationService {
isIncrementalDirection,
true,
component.layout,
this.writingDirection,
this.writingDirection
);

return isVerticalDirection
? isIncrementalDirection
? siblingCutoffCoordinate >= currentCutoffCoordinate // vertical next
: siblingCutoffCoordinate <= currentCutoffCoordinate // vertical previous
: this.writingDirection === WritingDirection.LTR
? isIncrementalDirection
? siblingCutoffCoordinate >= currentCutoffCoordinate // horizontal LTR next
: siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal LTR previous
: isIncrementalDirection
? siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal RTL next
: siblingCutoffCoordinate >= currentCutoffCoordinate // horizontal RTL previous
;
? isIncrementalDirection
? siblingCutoffCoordinate >= currentCutoffCoordinate // horizontal LTR next
: siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal LTR previous
: isIncrementalDirection
? siblingCutoffCoordinate <= currentCutoffCoordinate // horizontal RTL next
: siblingCutoffCoordinate >= currentCutoffCoordinate; // horizontal RTL previous
}

return false;
Expand Down Expand Up @@ -1087,7 +1099,17 @@ class SpatialNavigationService {
*/
const sortedForceFocusableComponents = this.sortSiblingsByPriority(
forceFocusableComponents,
{ x: 0, y: 0, width: 0, height: 0, left: 0, top: 0, right: 0, bottom: 0, node: null },
{
x: 0,
y: 0,
width: 0,
height: 0,
left: 0,
top: 0,
right: 0,
bottom: 0,
node: null
},
'down',
ROOT_FOCUS_KEY
);
Expand Down Expand Up @@ -1167,7 +1189,10 @@ class SpatialNavigationService {
* Otherwise, trying to focus something by coordinates
*/
children.forEach((component) => this.updateLayout(component.focusKey));
const { focusKey: childKey } = getChildClosestToOrigin(children, this.writingDirection);
const { focusKey: childKey } = getChildClosestToOrigin(
children,
this.writingDirection
);

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

Expand Down

0 comments on commit 80b4385

Please sign in to comment.