-
Notifications
You must be signed in to change notification settings - Fork 45.6k
/
FocusManager.js
127 lines (117 loc) · 2.99 KB
/
FocusManager.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {ReactScopeMethods} from 'shared/ReactTypes';
import type {KeyboardEvent} from 'react-interactions/events/keyboard';
import getTabbableNodes from './shared/getTabbableNodes';
export function focusFirst(
scopeQuery: (type: string | Object, props: Object) => boolean,
scope: ReactScopeMethods,
): void {
const firstNode = scope.queryFirstNode(scopeQuery);
if (firstNode) {
focusElem(firstNode);
}
}
function focusElem(elem: null | HTMLElement): void {
if (elem !== null) {
elem.focus();
}
}
export function focusNext(
scopeQuery: (type: string | Object, props: Object) => boolean,
scope: ReactScopeMethods,
event?: KeyboardEvent,
contain?: boolean,
): void {
const [
tabbableNodes,
firstTabbableElem,
lastTabbableElem,
currentIndex,
focusedElement,
] = getTabbableNodes(scopeQuery, scope);
if (focusedElement === null) {
if (event) {
event.continuePropagation();
}
} else if (focusedElement === lastTabbableElem) {
if (contain === true) {
focusElem(firstTabbableElem);
if (event) {
event.preventDefault();
}
} else if (event) {
event.continuePropagation();
}
} else if (tabbableNodes) {
focusElem(tabbableNodes[currentIndex + 1]);
if (event) {
event.preventDefault();
}
}
}
export function focusPrevious(
scopeQuery: (type: string | Object, props: Object) => boolean,
scope: ReactScopeMethods,
event?: KeyboardEvent,
contain?: boolean,
): void {
const [
tabbableNodes,
firstTabbableElem,
lastTabbableElem,
currentIndex,
focusedElement,
] = getTabbableNodes(scopeQuery, scope);
if (focusedElement === null) {
if (event) {
event.continuePropagation();
}
} else if (focusedElement === firstTabbableElem) {
if (contain === true) {
focusElem(lastTabbableElem);
if (event) {
event.preventDefault();
}
} else if (event) {
event.continuePropagation();
}
} else if (tabbableNodes) {
focusElem(tabbableNodes[currentIndex - 1]);
if (event) {
event.preventDefault();
}
}
}
export function getNextScope(
scope: ReactScopeMethods,
): null | ReactScopeMethods {
const allScopes = scope.getChildrenFromRoot();
if (allScopes === null) {
return null;
}
const currentScopeIndex = allScopes.indexOf(scope);
if (currentScopeIndex === -1 || currentScopeIndex === allScopes.length - 1) {
return null;
}
return allScopes[currentScopeIndex + 1];
}
export function getPreviousScope(
scope: ReactScopeMethods,
): null | ReactScopeMethods {
const allScopes = scope.getChildrenFromRoot();
if (allScopes === null) {
return null;
}
const currentScopeIndex = allScopes.indexOf(scope);
if (currentScopeIndex <= 0) {
return null;
}
return allScopes[currentScopeIndex - 1];
}