Skip to content

Commit b78cdec

Browse files
Focusable container agnostic methods available as top level exports + doesFocusableExist (#94)
Co-authored-by: Dmitriy Bryokhin <asgvard@gmail.com>
1 parent 77b4f7d commit b78cdec

3 files changed

Lines changed: 49 additions & 43 deletions

File tree

README.md

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ It is useful when you first open the page, or i.e. when your modal Popup gets mo
112112

113113
```jsx
114114
import React, { useEffect } from 'react';
115-
import { useFocusable, FocusContext } from '@noriginmedia/norigin-spatial-navigation';
115+
import { useFocusable, FocusContext, setFocus } from '@noriginmedia/norigin-spatial-navigation';
116116

117117
function Popup() {
118-
const { ref, focusKey, focusSelf, setFocus } = useFocusable();
118+
const { ref, focusKey, focusSelf } = useFocusable();
119119

120120
// Focusing self will focus the Popup, which will pass the focus down to the first Child (ButtonPrimary)
121121
// Alternatively you can manually focus any other component by its 'focusKey'
@@ -297,6 +297,31 @@ setThrottle({
297297
### `destroy`
298298
Resets all the settings and the storage of focusable components. Disables the navigation service.
299299

300+
### `doesFocusableExist` (function) `(focusKey: string) => boolean`
301+
Returns `true` if Focusable Container with given `focusKey` is created, `false` otherwise.
302+
303+
### `setFocus` (function) `(focusKey: string) => void`
304+
Method to manually set the focus to a component providing its `focusKey`. If `focusKey` is not provided or
305+
is equal to `ROOT_FOCUS_KEY`, an attempt of focusing one of the force-focusable components is made.
306+
See `useFocusable` hook [`forceFocus`](#forcefocus-default-false) parameter for more details.
307+
308+
### `getCurrentFocusKey` (function) `() => string`
309+
Returns the currently focused component's focus key.
310+
311+
### `navigateByDirection` (function) `(direction: string, focusDetails: FocusDetails) => void`
312+
Method to manually navigation to a certain direction. I.e. you can assign a mouse-wheel to navigate Up and Down.
313+
Also useful when you have some "Arrow-like" UI in the app that is meant to navigate in certain direction when pressed
314+
with the mouse or a "magic remote" on some TVs.
315+
316+
### `pause` (function)
317+
Pauses all the key event handlers.
318+
319+
### `resume` (function)
320+
Resumes all the key event handlers.
321+
322+
### `updateAllLayouts` (function)
323+
Manually recalculate all the layouts. Rarely used.
324+
300325
### `useFocusable` hook
301326
This hook is the main link between the React component (its DOM element) and the navigation service.
302327
It is used to register the component in the service, get its `focusKey`, `focused` state etc.
@@ -398,11 +423,6 @@ function Button() {
398423
Method to set the focus on the current component. I.e. to set the focus to the Page (Container) when it is mounted, or
399424
the Popup component when it is displayed.
400425

401-
##### `setFocus` (function) `(focusKey: string) => void`
402-
Method to manually set the focus to a component providing its `focusKey`. If `focusKey` is not provided or
403-
is equal to `ROOT_FOCUS_KEY`, an attempt of focusing one of the force-focusable components is made.
404-
See `useFocusable` hook [`forceFocus`](#forcefocus-default-false) parameter for more details.
405-
406426
##### `focused` (boolean)
407427
Flag that indicates that the current component is focused.
408428

@@ -414,23 +434,6 @@ Only works when `trackChildren` is enabled!
414434
String that contains the focus key for the component. It is either the same as `focusKey` passed to the hook params,
415435
or an automatically generated one.
416436

417-
#### `getCurrentFocusKey` (function) `() => string`
418-
Returns the currently focused component's focus key.
419-
420-
##### `navigateByDirection` (function) `(direction: string, focusDetails: FocusDetails) => void`
421-
Method to manually navigation to a certain direction. I.e. you can assign a mouse-wheel to navigate Up and Down.
422-
Also useful when you have some "Arrow-like" UI in the app that is meant to navigate in certain direction when pressed
423-
with the mouse or a "magic remote" on some TVs.
424-
425-
##### `pause` (function)
426-
Pauses all the key event handlers.
427-
428-
##### `resume` (function)
429-
Resumes all the key event handlers.
430-
431-
##### `updateAllLayouts` (function)
432-
Manually recalculate all the layouts. Rarely used.
433-
434437
### `FocusContext` (required for Focusable Containers)
435438
Used to provide the `focusKey` of the current Focusable Container down the Tree to the next child level. [See Example](#wrapping-leaf-components-with-a-focusable-container)
436439

src/SpatialNavigation.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ class SpatialNavigationService {
561561
this.destroy = this.destroy.bind(this);
562562
this.setKeyMap = this.setKeyMap.bind(this);
563563
this.getCurrentFocusKey = this.getCurrentFocusKey.bind(this);
564+
this.doesFocusableExist = this.doesFocusableExist.bind(this);
564565

565566
this.setFocusDebounced = debounce(this.setFocus, AUTO_RESTORE_FOCUS_DELAY, {
566567
leading: false,
@@ -826,7 +827,7 @@ class SpatialNavigationService {
826827
* navigateByDirection('right') // The focus is moved to right
827828
*/
828829
navigateByDirection(direction: string, focusDetails: FocusDetails) {
829-
if (this.paused === true || this.nativeMode) {
830+
if (this.paused === true || !this.enabled || this.nativeMode) {
830831
return;
831832
}
832833

@@ -1483,7 +1484,7 @@ class SpatialNavigationService {
14831484
// Cancel any pending auto-restore focus calls if we are setting focus manually
14841485
this.setFocusDebounced.cancel();
14851486

1486-
if (!this.enabled) {
1487+
if (!this.enabled || this.nativeMode) {
14871488
return;
14881489
}
14891490

@@ -1509,7 +1510,7 @@ class SpatialNavigationService {
15091510
}
15101511

15111512
updateAllLayouts() {
1512-
if (this.nativeMode) {
1513+
if (!this.enabled || this.nativeMode) {
15131514
return;
15141515
}
15151516

@@ -1578,6 +1579,10 @@ class SpatialNavigationService {
15781579
isNativeMode() {
15791580
return this.nativeMode;
15801581
}
1582+
1583+
doesFocusableExist(focusKey: string) {
1584+
return !!this.focusableComponents[focusKey];
1585+
}
15811586
}
15821587

15831588
/**
@@ -1586,4 +1591,16 @@ class SpatialNavigationService {
15861591
/** @internal */
15871592
export const SpatialNavigation = new SpatialNavigationService();
15881593

1589-
export const { init, setThrottle, destroy, setKeyMap } = SpatialNavigation;
1594+
export const {
1595+
init,
1596+
setThrottle,
1597+
destroy,
1598+
setKeyMap,
1599+
setFocus,
1600+
navigateByDirection,
1601+
pause,
1602+
resume,
1603+
updateAllLayouts,
1604+
getCurrentFocusKey,
1605+
doesFocusableExist
1606+
} = SpatialNavigation;

src/useFocusable.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,6 @@ export interface UseFocusableResult {
6565
focused: boolean;
6666
hasFocusedChild: boolean;
6767
focusKey: string;
68-
setFocus: (focusKey: string, focusDetails?: FocusDetails) => void;
69-
navigateByDirection: (direction: string, focusDetails: FocusDetails) => void;
70-
pause: () => void;
71-
resume: () => void;
72-
updateAllLayouts: () => void;
73-
getCurrentFocusKey: () => string;
7468
}
7569

7670
const useFocusableHook = <P>({
@@ -208,15 +202,7 @@ const useFocusableHook = <P>({
208202
focusSelf,
209203
focused,
210204
hasFocusedChild,
211-
focusKey, // returns either the same focusKey as passed in, or generated one
212-
setFocus: SpatialNavigation.isNativeMode()
213-
? noop
214-
: SpatialNavigation.setFocus,
215-
navigateByDirection: SpatialNavigation.navigateByDirection,
216-
pause: SpatialNavigation.pause,
217-
resume: SpatialNavigation.resume,
218-
updateAllLayouts: SpatialNavigation.updateAllLayouts,
219-
getCurrentFocusKey: SpatialNavigation.getCurrentFocusKey
205+
focusKey // returns either the same focusKey as passed in, or generated one
220206
};
221207
};
222208

0 commit comments

Comments
 (0)