@instructure/ui-a11y-utils 8.33.2-snapshot-0 → 8.33.2
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/CHANGELOG.md +1 -5
- package/es/FocusRegion.js +6 -40
- package/es/FocusRegionManager.js +10 -33
- package/es/KeyboardFocusRegion.js +4 -53
- package/es/ScreenReaderFocusRegion.js +1 -36
- package/es/hasVisibleChildren.js +1 -2
- package/es/index.js +1 -0
- package/es/scopeTab.js +8 -12
- package/lib/FocusRegion.js +6 -50
- package/lib/FocusRegionManager.js +10 -38
- package/lib/KeyboardFocusRegion.js +4 -66
- package/lib/ScreenReaderFocusRegion.js +1 -37
- package/lib/hasVisibleChildren.js +1 -8
- package/lib/index.js +0 -6
- package/lib/scopeTab.js +8 -17
- package/package.json +10 -10
- package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,14 +3,10 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [8.33.2
|
|
6
|
+
## [8.33.2](https://github.com/instructure/instructure-ui/compare/v8.33.1...v8.33.2) (2023-01-25)
|
|
7
7
|
|
|
8
8
|
**Note:** Version bump only for package @instructure/ui-a11y-utils
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
10
|
## [8.33.1](https://github.com/instructure/instructure-ui/compare/v8.33.0...v8.33.1) (2023-01-06)
|
|
15
11
|
|
|
16
12
|
**Note:** Version bump only for package @instructure/ui-a11y-utils
|
package/es/FocusRegion.js
CHANGED
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
|
+
|
|
24
25
|
import keycode from 'keycode';
|
|
25
26
|
import { contains, addEventListener, ownerDocument, findTabbable } from '@instructure/ui-dom-utils';
|
|
26
27
|
import { uid } from '@instructure/uid';
|
|
27
28
|
import { logError as error } from '@instructure/console';
|
|
28
29
|
import { ScreenReaderFocusRegion } from './ScreenReaderFocusRegion';
|
|
29
30
|
import { KeyboardFocusRegion } from './KeyboardFocusRegion';
|
|
30
|
-
|
|
31
31
|
class FocusRegion {
|
|
32
32
|
constructor(element, options) {
|
|
33
33
|
this._contextElement = null;
|
|
@@ -38,37 +38,30 @@ class FocusRegion {
|
|
|
38
38
|
this._id = void 0;
|
|
39
39
|
this._listeners = [];
|
|
40
40
|
this._active = false;
|
|
41
|
-
|
|
42
41
|
this.handleDismiss = (event, documentClick) => {
|
|
43
42
|
var _this$_options$onDism, _this$_options;
|
|
44
|
-
|
|
45
43
|
(_this$_options$onDism = (_this$_options = this._options).onDismiss) === null || _this$_options$onDism === void 0 ? void 0 : _this$_options$onDism.call(_this$_options, event, documentClick);
|
|
46
44
|
};
|
|
47
|
-
|
|
48
45
|
this.captureDocumentClick = event => {
|
|
49
46
|
const target = event.target;
|
|
50
47
|
this._preventCloseOnDocumentClick = event.button !== 0 || contains(this._contextElement, target);
|
|
51
48
|
};
|
|
52
|
-
|
|
53
49
|
this.handleDocumentClick = event => {
|
|
54
50
|
if (this._options.shouldCloseOnDocumentClick && !this._preventCloseOnDocumentClick) {
|
|
55
51
|
this.handleDismiss(event, true);
|
|
56
52
|
}
|
|
57
53
|
};
|
|
58
|
-
|
|
59
54
|
this.handleFrameClick = (event, frame) => {
|
|
60
55
|
if (!contains(this._contextElement, frame)) {
|
|
61
56
|
// dismiss if frame is not within the region
|
|
62
57
|
this.handleDismiss(event, true);
|
|
63
58
|
}
|
|
64
59
|
};
|
|
65
|
-
|
|
66
60
|
this.handleKeyUp = event => {
|
|
67
61
|
if (this._options.shouldCloseOnEscape && event.keyCode === keycode.codes.esc && !event.defaultPrevented) {
|
|
68
62
|
this.handleDismiss(event);
|
|
69
63
|
}
|
|
70
64
|
};
|
|
71
|
-
|
|
72
65
|
this._options = options || {
|
|
73
66
|
shouldCloseOnDocumentClick: true,
|
|
74
67
|
shouldCloseOnEscape: true
|
|
@@ -78,54 +71,41 @@ class FocusRegion {
|
|
|
78
71
|
this._keyboardFocusRegion = new KeyboardFocusRegion(element, options);
|
|
79
72
|
this._id = uid();
|
|
80
73
|
}
|
|
81
|
-
|
|
82
74
|
updateElement(element, options) {
|
|
83
75
|
this._contextElement = element;
|
|
84
|
-
|
|
85
76
|
if (options) {
|
|
86
77
|
this._options = options;
|
|
87
78
|
}
|
|
88
|
-
|
|
89
79
|
if (this._keyboardFocusRegion) {
|
|
90
80
|
this._keyboardFocusRegion.updateElement(element);
|
|
91
81
|
}
|
|
92
|
-
|
|
93
82
|
if (this._screenReaderFocusRegion) {
|
|
94
83
|
this._screenReaderFocusRegion.updateElement(element);
|
|
95
84
|
}
|
|
96
85
|
}
|
|
97
|
-
|
|
98
86
|
get id() {
|
|
99
87
|
return this._id;
|
|
100
|
-
}
|
|
101
|
-
// is inconsistent across browsers (Safari/Firefox do not focus elements on click)
|
|
102
|
-
|
|
88
|
+
}
|
|
103
89
|
|
|
90
|
+
// Focused returns when the focus region is active. Checking focused with the active element
|
|
91
|
+
// is inconsistent across browsers (Safari/Firefox do not focus elements on click)
|
|
104
92
|
get focused() {
|
|
105
93
|
return this._active;
|
|
106
94
|
}
|
|
107
|
-
|
|
108
95
|
get keyboardFocusable() {
|
|
109
96
|
return (findTabbable(this._contextElement) || []).length > 0;
|
|
110
97
|
}
|
|
111
|
-
|
|
112
98
|
activate() {
|
|
113
99
|
if (!this._active) {
|
|
114
100
|
const doc = ownerDocument(this._contextElement);
|
|
115
|
-
|
|
116
101
|
this._keyboardFocusRegion.activate();
|
|
117
|
-
|
|
118
102
|
this._screenReaderFocusRegion.activate();
|
|
119
|
-
|
|
120
103
|
if (this._options.shouldCloseOnDocumentClick) {
|
|
121
104
|
this._listeners.push(addEventListener(doc, 'click', this.captureDocumentClick, true));
|
|
122
|
-
|
|
123
105
|
this._listeners.push(addEventListener(doc, 'click', this.handleDocumentClick));
|
|
124
|
-
|
|
125
106
|
Array.from(doc.getElementsByTagName('iframe')).forEach(el => {
|
|
126
107
|
// listen for mouseup events on any iframes in the document
|
|
127
108
|
const frameDoc = el.contentDocument;
|
|
128
|
-
|
|
129
109
|
if (frameDoc) {
|
|
130
110
|
this._listeners.push(addEventListener(frameDoc, 'mouseup', event => {
|
|
131
111
|
this.handleFrameClick(event, el);
|
|
@@ -133,51 +113,37 @@ class FocusRegion {
|
|
|
133
113
|
}
|
|
134
114
|
});
|
|
135
115
|
}
|
|
136
|
-
|
|
137
116
|
if (this._options.shouldCloseOnEscape) {
|
|
138
117
|
this._listeners.push(addEventListener(doc, 'keyup', this.handleKeyUp));
|
|
139
118
|
}
|
|
140
|
-
|
|
141
119
|
this._active = true;
|
|
142
120
|
}
|
|
143
121
|
}
|
|
144
|
-
|
|
145
122
|
deactivate() {
|
|
146
123
|
let _ref = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {},
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
124
|
+
_ref$keyboard = _ref.keyboard,
|
|
125
|
+
keyboard = _ref$keyboard === void 0 ? true : _ref$keyboard;
|
|
150
126
|
if (this._active) {
|
|
151
127
|
this._listeners.forEach(listener => {
|
|
152
128
|
listener.remove();
|
|
153
129
|
});
|
|
154
|
-
|
|
155
130
|
this._listeners = [];
|
|
156
|
-
|
|
157
131
|
if (keyboard) {
|
|
158
132
|
this._keyboardFocusRegion.deactivate();
|
|
159
133
|
}
|
|
160
|
-
|
|
161
134
|
this._screenReaderFocusRegion.deactivate();
|
|
162
|
-
|
|
163
135
|
this._active = false;
|
|
164
136
|
}
|
|
165
137
|
}
|
|
166
|
-
|
|
167
138
|
focus() {
|
|
168
139
|
error(this._active, `[FocusRegion] Cannot call '.focus()' on a region that is not currently active.`);
|
|
169
|
-
|
|
170
140
|
this._keyboardFocusRegion.focus();
|
|
171
141
|
}
|
|
172
|
-
|
|
173
142
|
blur() {
|
|
174
143
|
error(!this._active, `[FocusRegion] Cannot call '.blur()' on a region that is currently active.`);
|
|
175
|
-
|
|
176
144
|
this._keyboardFocusRegion.blur();
|
|
177
145
|
}
|
|
178
|
-
|
|
179
146
|
}
|
|
180
|
-
|
|
181
147
|
export default FocusRegion;
|
|
182
148
|
export {
|
|
183
149
|
/**
|
package/es/FocusRegionManager.js
CHANGED
|
@@ -21,62 +21,50 @@
|
|
|
21
21
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
|
+
|
|
24
25
|
import { logError as error } from '@instructure/console';
|
|
25
26
|
import { FocusRegion } from './FocusRegion';
|
|
26
27
|
let ENTRIES = [];
|
|
27
|
-
|
|
28
28
|
class FocusRegionManager {}
|
|
29
|
-
|
|
30
29
|
FocusRegionManager.focusRegion = function (element) {
|
|
31
30
|
let idOrOptions = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
32
31
|
let entry;
|
|
33
|
-
|
|
34
32
|
if (typeof idOrOptions === 'string') {
|
|
35
33
|
entry = FocusRegionManager.getEntry(element, idOrOptions);
|
|
36
34
|
} else {
|
|
37
35
|
entry = FocusRegionManager.addEntry(element, idOrOptions);
|
|
38
36
|
}
|
|
39
|
-
|
|
40
37
|
if (entry && entry.region && typeof entry.region.focus === 'function') {
|
|
41
38
|
entry.region.focus();
|
|
42
39
|
return entry.region;
|
|
43
40
|
} else {
|
|
44
41
|
error(false, `[FocusRegionManager] Could not focus region with element: ${element}`);
|
|
45
42
|
}
|
|
46
|
-
|
|
47
43
|
return;
|
|
48
44
|
};
|
|
49
|
-
|
|
50
45
|
FocusRegionManager.activateRegion = (element, options) => {
|
|
51
46
|
const _FocusRegionManager$a = FocusRegionManager.addEntry(element, options),
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
region = _FocusRegionManager$a.region;
|
|
54
48
|
return region;
|
|
55
49
|
};
|
|
56
|
-
|
|
57
50
|
FocusRegionManager.getActiveEntry = () => {
|
|
58
51
|
return ENTRIES.find(_ref => {
|
|
59
52
|
let region = _ref.region;
|
|
60
53
|
return region.focused;
|
|
61
54
|
});
|
|
62
55
|
};
|
|
63
|
-
|
|
64
56
|
FocusRegionManager.findEntry = (element, id) => {
|
|
65
57
|
let index;
|
|
66
|
-
|
|
67
58
|
if (id) {
|
|
68
59
|
index = ENTRIES.findIndex(entry => entry.id === id);
|
|
69
60
|
} else {
|
|
70
61
|
index = ENTRIES.findIndex(entry => entry.element === element);
|
|
71
62
|
}
|
|
72
|
-
|
|
73
63
|
return index;
|
|
74
64
|
};
|
|
75
|
-
|
|
76
65
|
FocusRegionManager.getEntry = (element, id) => {
|
|
77
66
|
return ENTRIES[FocusRegionManager.findEntry(element, id)];
|
|
78
67
|
};
|
|
79
|
-
|
|
80
68
|
FocusRegionManager.addEntry = function (element) {
|
|
81
69
|
let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
82
70
|
const region = new FocusRegion(element, options);
|
|
@@ -84,7 +72,6 @@ FocusRegionManager.addEntry = function (element) {
|
|
|
84
72
|
const keyboardFocusable = region.keyboardFocusable;
|
|
85
73
|
ENTRIES.forEach(_ref2 => {
|
|
86
74
|
let region = _ref2.region;
|
|
87
|
-
|
|
88
75
|
if (region) {
|
|
89
76
|
// If the active region is triggering a new focus region that does not have
|
|
90
77
|
// keyboard focusable content, don't deactivate the active region's keyboard
|
|
@@ -96,11 +83,9 @@ FocusRegionManager.addEntry = function (element) {
|
|
|
96
83
|
}
|
|
97
84
|
});
|
|
98
85
|
region.activate();
|
|
99
|
-
|
|
100
86
|
if (options.shouldFocusOnOpen) {
|
|
101
87
|
region.focus();
|
|
102
88
|
}
|
|
103
|
-
|
|
104
89
|
const entry = {
|
|
105
90
|
id: region.id,
|
|
106
91
|
element,
|
|
@@ -109,59 +94,51 @@ FocusRegionManager.addEntry = function (element) {
|
|
|
109
94
|
parent: activeEntry
|
|
110
95
|
};
|
|
111
96
|
ENTRIES.push(entry);
|
|
112
|
-
|
|
113
97
|
if (activeEntry) {
|
|
114
98
|
activeEntry.children.push(entry);
|
|
115
99
|
}
|
|
116
|
-
|
|
117
100
|
return entry;
|
|
118
101
|
};
|
|
119
|
-
|
|
120
102
|
FocusRegionManager.removeEntry = (element, id) => {
|
|
121
103
|
const index = FocusRegionManager.findEntry(element, id);
|
|
122
104
|
const entry = ENTRIES[index];
|
|
123
|
-
|
|
124
105
|
if (index > -1) {
|
|
125
106
|
ENTRIES.splice(index, 1);
|
|
126
107
|
}
|
|
127
|
-
|
|
128
108
|
return entry;
|
|
129
109
|
};
|
|
130
|
-
|
|
131
110
|
FocusRegionManager.isFocused = (element, id) => {
|
|
132
111
|
const entry = FocusRegionManager.getActiveEntry();
|
|
133
|
-
|
|
134
112
|
if (id) {
|
|
135
113
|
return entry && entry.region && entry.id === id;
|
|
136
114
|
} else {
|
|
137
115
|
return entry && entry.region && entry.element === element;
|
|
138
116
|
}
|
|
139
117
|
};
|
|
140
|
-
|
|
141
118
|
FocusRegionManager.clearEntries = () => {
|
|
142
119
|
ENTRIES = [];
|
|
143
120
|
};
|
|
144
|
-
|
|
145
121
|
FocusRegionManager.blurRegion = (element, id) => {
|
|
146
122
|
const entry = FocusRegionManager.removeEntry(element, id);
|
|
147
|
-
|
|
148
123
|
if (entry) {
|
|
149
124
|
const children = entry.children,
|
|
150
|
-
|
|
151
|
-
|
|
125
|
+
region = entry.region,
|
|
126
|
+
parent = entry.parent;
|
|
152
127
|
|
|
153
|
-
|
|
128
|
+
// deactivate the region...
|
|
129
|
+
region && region.deactivate();
|
|
154
130
|
|
|
131
|
+
// and any regions created from it
|
|
155
132
|
if (children) {
|
|
156
133
|
children.forEach(_ref3 => {
|
|
157
134
|
let id = _ref3.id,
|
|
158
|
-
|
|
135
|
+
element = _ref3.element;
|
|
159
136
|
const entry = FocusRegionManager.removeEntry(element, id);
|
|
160
137
|
entry && entry.region && entry.region.deactivate();
|
|
161
138
|
});
|
|
162
|
-
}
|
|
163
|
-
|
|
139
|
+
}
|
|
164
140
|
|
|
141
|
+
// activate the region's parent if it exists
|
|
165
142
|
parent && parent.region && parent.region.activate();
|
|
166
143
|
region && region.blur(); // this should focus the parent region
|
|
167
144
|
}
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
|
+
|
|
24
25
|
import { findDOMNode, findTabbable, findFocusable, ownerWindow, getActiveElement, addEventListener, ownerDocument, containsActiveElement, requestAnimationFrame } from '@instructure/ui-dom-utils';
|
|
25
26
|
import { logError as error } from '@instructure/console';
|
|
26
27
|
import keycode from 'keycode';
|
|
27
28
|
import { scopeTab } from './scopeTab';
|
|
28
|
-
|
|
29
29
|
class KeyboardFocusRegion {
|
|
30
30
|
constructor(element, options) {
|
|
31
31
|
this._options = void 0;
|
|
@@ -36,141 +36,110 @@ class KeyboardFocusRegion {
|
|
|
36
36
|
this._active = false;
|
|
37
37
|
this._wasDocumentClick = void 0;
|
|
38
38
|
this._contextElement = void 0;
|
|
39
|
-
|
|
40
39
|
this.handleKeyDown = event => {
|
|
41
40
|
if (event.keyCode === keycode.codes.tab) {
|
|
42
41
|
scopeTab(this._contextElement, event);
|
|
43
42
|
}
|
|
44
43
|
};
|
|
45
|
-
|
|
46
44
|
this.handleClick = () => {
|
|
47
45
|
this._wasDocumentClick = true;
|
|
48
46
|
};
|
|
49
|
-
|
|
50
47
|
this.handleWindowBlur = () => {
|
|
51
48
|
if (this._wasDocumentClick) {
|
|
52
49
|
this._wasDocumentClick = false;
|
|
53
50
|
return;
|
|
54
51
|
}
|
|
55
|
-
|
|
56
52
|
this._needToFocus = true;
|
|
57
53
|
};
|
|
58
|
-
|
|
59
54
|
this.handleFocus = () => {
|
|
60
55
|
if (this._needToFocus) {
|
|
61
56
|
this._needToFocus = false;
|
|
62
|
-
|
|
63
57
|
if (!this._contextElement) {
|
|
64
58
|
return;
|
|
65
|
-
}
|
|
59
|
+
}
|
|
60
|
+
// need to see how jQuery shims document.on('focusin') so we don't need the
|
|
66
61
|
// setTimeout, firefox doesn't support focusin, if it did, we could focus
|
|
67
62
|
// the element outside of a setTimeout. Side-effect of this implementation
|
|
68
63
|
// is that the document.body gets focus, and then we focus our element right
|
|
69
64
|
// after, seems fine.
|
|
70
|
-
|
|
71
|
-
|
|
72
65
|
this._raf.push(requestAnimationFrame(() => {
|
|
73
66
|
if (containsActiveElement(this._contextElement)) {
|
|
74
67
|
return;
|
|
75
68
|
}
|
|
76
|
-
|
|
77
69
|
this.focusDefaultElement();
|
|
78
70
|
}));
|
|
79
71
|
}
|
|
80
72
|
};
|
|
81
|
-
|
|
82
73
|
this.handleFirstTabbableKeyDown = event => {
|
|
83
74
|
if (event.keyCode === keycode.codes.tab && event.shiftKey) {
|
|
84
75
|
var _this$_options$onBlur, _this$_options;
|
|
85
|
-
|
|
86
76
|
(_this$_options$onBlur = (_this$_options = this._options).onBlur) === null || _this$_options$onBlur === void 0 ? void 0 : _this$_options$onBlur.call(_this$_options, event);
|
|
87
77
|
}
|
|
88
78
|
};
|
|
89
|
-
|
|
90
79
|
this.handleLastTabbableKeyDown = event => {
|
|
91
80
|
if (event.keyCode === keycode.codes.tab && !event.shiftKey) {
|
|
92
81
|
var _this$_options$onBlur2, _this$_options2;
|
|
93
|
-
|
|
94
82
|
(_this$_options$onBlur2 = (_this$_options2 = this._options).onBlur) === null || _this$_options$onBlur2 === void 0 ? void 0 : _this$_options$onBlur2.call(_this$_options2, event);
|
|
95
83
|
}
|
|
96
84
|
};
|
|
97
|
-
|
|
98
85
|
this._contextElement = findDOMNode(element);
|
|
99
86
|
this._options = options || {
|
|
100
87
|
shouldContainFocus: true,
|
|
101
88
|
shouldReturnFocus: true,
|
|
102
89
|
defaultFocusElement: null
|
|
103
90
|
};
|
|
104
|
-
|
|
105
91
|
if (this._options.shouldReturnFocus) {
|
|
106
92
|
this._focusLaterElement = getActiveElement(this.doc);
|
|
107
93
|
}
|
|
108
94
|
}
|
|
109
|
-
|
|
110
95
|
get focused() {
|
|
111
96
|
return containsActiveElement(this._contextElement);
|
|
112
97
|
}
|
|
113
|
-
|
|
114
98
|
get shouldContainFocus() {
|
|
115
99
|
const shouldContainFocus = this._options.shouldContainFocus;
|
|
116
100
|
return shouldContainFocus === true || Array.isArray(shouldContainFocus) && shouldContainFocus.includes('keyboard');
|
|
117
101
|
}
|
|
118
|
-
|
|
119
102
|
get focusable() {
|
|
120
103
|
return findFocusable(this._contextElement, () => true, true) || [];
|
|
121
104
|
}
|
|
122
|
-
|
|
123
105
|
get tabbable() {
|
|
124
106
|
return findTabbable(this._contextElement) || [];
|
|
125
107
|
}
|
|
126
|
-
|
|
127
108
|
get firstTabbable() {
|
|
128
109
|
return this.tabbable[0];
|
|
129
110
|
}
|
|
130
|
-
|
|
131
111
|
get lastTabbable() {
|
|
132
112
|
return this.tabbable.pop();
|
|
133
113
|
}
|
|
134
|
-
|
|
135
114
|
get firstFocusable() {
|
|
136
115
|
return this.focusable[0];
|
|
137
116
|
}
|
|
138
|
-
|
|
139
117
|
get lastFocusable() {
|
|
140
118
|
return this.focusable.pop();
|
|
141
119
|
}
|
|
142
|
-
|
|
143
120
|
get doc() {
|
|
144
121
|
return ownerDocument(this._contextElement);
|
|
145
122
|
}
|
|
146
|
-
|
|
147
123
|
get win() {
|
|
148
124
|
return ownerWindow(this._contextElement);
|
|
149
125
|
}
|
|
150
|
-
|
|
151
126
|
get defaultFocusElement() {
|
|
152
127
|
const defaultFocusElement = this._options.defaultFocusElement;
|
|
153
128
|
const element = findDOMNode(typeof defaultFocusElement === 'function' ? defaultFocusElement() : defaultFocusElement);
|
|
154
|
-
|
|
155
129
|
if (element && this._contextElement && this._contextElement.contains(element)) {
|
|
156
130
|
return element;
|
|
157
131
|
}
|
|
158
|
-
|
|
159
132
|
if (this.firstTabbable) {
|
|
160
133
|
return this.firstTabbable;
|
|
161
134
|
}
|
|
162
|
-
|
|
163
135
|
if (this._contextElement && this.focusable.includes(this._contextElement)) {
|
|
164
136
|
return this._contextElement;
|
|
165
137
|
}
|
|
166
|
-
|
|
167
138
|
return null;
|
|
168
139
|
}
|
|
169
|
-
|
|
170
140
|
updateElement(element) {
|
|
171
141
|
this._contextElement = findDOMNode(element);
|
|
172
142
|
}
|
|
173
|
-
|
|
174
143
|
focusDefaultElement() {
|
|
175
144
|
if (this.defaultFocusElement) {
|
|
176
145
|
;
|
|
@@ -186,22 +155,18 @@ class KeyboardFocusRegion {
|
|
|
186
155
|
}
|
|
187
156
|
}
|
|
188
157
|
}
|
|
189
|
-
|
|
190
158
|
focus() {
|
|
191
159
|
if (this.focused) {
|
|
192
160
|
return;
|
|
193
161
|
}
|
|
194
|
-
|
|
195
162
|
this._raf.push(requestAnimationFrame(() => {
|
|
196
163
|
this.focusDefaultElement();
|
|
197
164
|
}));
|
|
198
165
|
}
|
|
199
|
-
|
|
200
166
|
blur() {
|
|
201
167
|
if (this._options.shouldReturnFocus && this._focusLaterElement) {
|
|
202
168
|
try {
|
|
203
169
|
;
|
|
204
|
-
|
|
205
170
|
this._focusLaterElement.focus();
|
|
206
171
|
} catch (e) {
|
|
207
172
|
error(false, `
|
|
@@ -209,53 +174,39 @@ class KeyboardFocusRegion {
|
|
|
209
174
|
but it is not in the DOM anymore: ${e}
|
|
210
175
|
`);
|
|
211
176
|
}
|
|
212
|
-
|
|
213
177
|
this._focusLaterElement = null;
|
|
214
178
|
}
|
|
215
179
|
}
|
|
216
|
-
|
|
217
180
|
activate() {
|
|
218
181
|
const defaultFocusElement = this.defaultFocusElement,
|
|
219
|
-
|
|
220
|
-
|
|
182
|
+
shouldContainFocus = this.shouldContainFocus;
|
|
221
183
|
if (!this._active) {
|
|
222
184
|
if (defaultFocusElement || shouldContainFocus) {
|
|
223
185
|
if (shouldContainFocus) {
|
|
224
186
|
this._listeners.push(addEventListener(this.doc, 'keydown', this.handleKeyDown));
|
|
225
187
|
} else {
|
|
226
188
|
this._listeners.push(addEventListener(this.firstTabbable || defaultFocusElement, 'keydown', this.handleFirstTabbableKeyDown));
|
|
227
|
-
|
|
228
189
|
this._listeners.push(addEventListener(this.lastTabbable || defaultFocusElement, 'keydown', this.handleLastTabbableKeyDown));
|
|
229
190
|
}
|
|
230
|
-
|
|
231
191
|
this._listeners.push(addEventListener(this.doc, 'click', this.handleClick, true));
|
|
232
|
-
|
|
233
192
|
this._listeners.push(addEventListener(this.win, 'blur', this.handleWindowBlur, false));
|
|
234
|
-
|
|
235
193
|
this._listeners.push(addEventListener(this.doc, 'focus', this.handleFocus, true));
|
|
236
|
-
|
|
237
194
|
this._active = true;
|
|
238
195
|
}
|
|
239
196
|
}
|
|
240
197
|
}
|
|
241
|
-
|
|
242
198
|
deactivate() {
|
|
243
199
|
if (this._active) {
|
|
244
200
|
this._listeners.forEach(listener => {
|
|
245
201
|
listener.remove();
|
|
246
202
|
});
|
|
247
|
-
|
|
248
203
|
this._listeners = [];
|
|
249
|
-
|
|
250
204
|
this._raf.forEach(request => request.cancel());
|
|
251
|
-
|
|
252
205
|
this._raf = [];
|
|
253
206
|
this._active = false;
|
|
254
207
|
}
|
|
255
208
|
}
|
|
256
|
-
|
|
257
209
|
}
|
|
258
|
-
|
|
259
210
|
export default KeyboardFocusRegion;
|
|
260
211
|
export {
|
|
261
212
|
/**
|