@instructure/ui-a11y-utils 8.12.0 → 8.12.1-snapshot.15
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/LICENSE.md +27 -0
- package/es/FocusRegion.js +15 -8
- package/es/FocusRegionManager.js +8 -4
- package/es/FocusRegionOptions.js +1 -0
- package/es/KeyboardFocusRegion.js +28 -35
- package/es/ScreenReaderFocusRegion.js +10 -6
- package/lib/FocusRegion.js +10 -7
- package/lib/FocusRegionManager.js +5 -2
- package/lib/FocusRegionOptions.js +1 -0
- package/lib/KeyboardFocusRegion.js +26 -34
- package/lib/ScreenReaderFocusRegion.js +7 -4
- package/package.json +12 -11
- package/src/FocusRegion.ts +42 -65
- package/src/FocusRegionManager.ts +35 -35
- package/src/FocusRegionOptions.ts +80 -0
- package/src/KeyboardFocusRegion.ts +58 -108
- package/src/ScreenReaderFocusRegion.ts +36 -78
- package/src/hasVisibleChildren.ts +2 -5
- package/src/index.ts +1 -0
- package/src/scopeTab.ts +7 -4
- package/types/FocusRegion.d.ts +22 -15
- package/types/FocusRegion.d.ts.map +1 -1
- package/types/FocusRegionManager.d.ts +23 -14
- package/types/FocusRegionManager.d.ts.map +1 -1
- package/types/FocusRegionOptions.d.ts +56 -0
- package/types/FocusRegionOptions.d.ts.map +1 -0
- package/types/KeyboardFocusRegion.d.ts +24 -22
- package/types/KeyboardFocusRegion.d.ts.map +1 -1
- package/types/ScreenReaderFocusRegion.d.ts +19 -17
- package/types/ScreenReaderFocusRegion.d.ts.map +1 -1
- package/types/hasVisibleChildren.d.ts +2 -1
- package/types/hasVisibleChildren.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/scopeTab.d.ts +2 -1
- package/types/scopeTab.d.ts.map +1 -1
package/LICENSE.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The MIT License (MIT)
|
|
3
|
+
category: Getting Started
|
|
4
|
+
order: 9
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# The MIT License (MIT)
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2015 Instructure, Inc.
|
|
10
|
+
|
|
11
|
+
**Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions.**
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
package/es/FocusRegion.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
import keycode from 'keycode';
|
|
25
|
-
import { contains, addEventListener,
|
|
25
|
+
import { contains, addEventListener, ownerDocument, findTabbable } from '@instructure/ui-dom-utils';
|
|
26
26
|
import { uid } from '@instructure/uid';
|
|
27
27
|
import { logError as error } from '@instructure/console';
|
|
28
28
|
import { ScreenReaderFocusRegion } from './ScreenReaderFocusRegion';
|
|
@@ -32,11 +32,17 @@ class FocusRegion {
|
|
|
32
32
|
constructor(element, options) {
|
|
33
33
|
this._contextElement = null;
|
|
34
34
|
this._preventCloseOnDocumentClick = false;
|
|
35
|
+
this._options = void 0;
|
|
36
|
+
this._screenReaderFocusRegion = void 0;
|
|
37
|
+
this._keyboardFocusRegion = void 0;
|
|
38
|
+
this._id = void 0;
|
|
35
39
|
this._listeners = [];
|
|
36
40
|
this._active = false;
|
|
37
41
|
|
|
38
42
|
this.handleDismiss = (event, documentClick) => {
|
|
39
|
-
|
|
43
|
+
var _this$_options$onDism, _this$_options;
|
|
44
|
+
|
|
45
|
+
(_this$_options$onDism = (_this$_options = this._options).onDismiss) === null || _this$_options$onDism === void 0 ? void 0 : _this$_options$onDism.call(_this$_options, event, documentClick);
|
|
40
46
|
};
|
|
41
47
|
|
|
42
48
|
this.captureDocumentClick = event => {
|
|
@@ -58,15 +64,14 @@ class FocusRegion {
|
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
this.handleKeyUp = event => {
|
|
61
|
-
if (this._options.shouldCloseOnEscape && event.keyCode === keycode.codes.
|
|
67
|
+
if (this._options.shouldCloseOnEscape && event.keyCode === keycode.codes.esc && !event.defaultPrevented) {
|
|
62
68
|
this.handleDismiss(event);
|
|
63
69
|
}
|
|
64
70
|
};
|
|
65
71
|
|
|
66
72
|
this._options = options || {
|
|
67
73
|
shouldCloseOnDocumentClick: true,
|
|
68
|
-
shouldCloseOnEscape: true
|
|
69
|
-
onDismiss: event => {}
|
|
74
|
+
shouldCloseOnEscape: true
|
|
70
75
|
};
|
|
71
76
|
this._contextElement = element;
|
|
72
77
|
this._screenReaderFocusRegion = new ScreenReaderFocusRegion(element, options);
|
|
@@ -115,7 +120,7 @@ class FocusRegion {
|
|
|
115
120
|
|
|
116
121
|
Array.from(doc.getElementsByTagName('iframe')).forEach(el => {
|
|
117
122
|
// listen for mouseup events on any iframes in the document
|
|
118
|
-
const frameDoc =
|
|
123
|
+
const frameDoc = el.contentDocument;
|
|
119
124
|
|
|
120
125
|
if (frameDoc) {
|
|
121
126
|
this._listeners.push(addEventListener(frameDoc, 'mouseup', event => {
|
|
@@ -173,10 +178,12 @@ export {
|
|
|
173
178
|
* ---
|
|
174
179
|
* category: utilities/a11y
|
|
175
180
|
* ---
|
|
176
|
-
*
|
|
177
|
-
* Class for focus operations
|
|
181
|
+
*
|
|
182
|
+
* Class for focus operations, manages [ScreenReaderFocusRegion](#ScreenReaderFocusRegion)
|
|
183
|
+
* and [KeyboardFocusRegion](#KeyboardFocusRegion) for the given DOM element.
|
|
178
184
|
* - Scoping focus within a given context (DOM node),
|
|
179
185
|
* - Mark active element for focus later
|
|
180
186
|
* - Return focus to the marked element
|
|
187
|
+
* @module FocusRegion
|
|
181
188
|
*/
|
|
182
189
|
FocusRegion };
|
package/es/FocusRegionManager.js
CHANGED
|
@@ -42,6 +42,8 @@ FocusRegionManager.focusRegion = (element, idOrOptions = {}) => {
|
|
|
42
42
|
} else {
|
|
43
43
|
error(false, `[FocusRegionManager] Could not focus region with element: ${element}`);
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
return;
|
|
45
47
|
};
|
|
46
48
|
|
|
47
49
|
FocusRegionManager.activateRegion = (element, options) => {
|
|
@@ -84,9 +86,10 @@ FocusRegionManager.addEntry = (element, options = {}) => {
|
|
|
84
86
|
// If the active region is triggering a new focus region that does not have
|
|
85
87
|
// keyboard focusable content, don't deactivate the active region's keyboard
|
|
86
88
|
// focus region
|
|
87
|
-
region.
|
|
89
|
+
const keyboard = region.focused && !keyboardFocusable ? {
|
|
88
90
|
keyboard: false
|
|
89
|
-
}
|
|
91
|
+
} : void 0;
|
|
92
|
+
region.deactivate(keyboard);
|
|
90
93
|
}
|
|
91
94
|
});
|
|
92
95
|
region.activate();
|
|
@@ -168,10 +171,11 @@ export {
|
|
|
168
171
|
* ---
|
|
169
172
|
* category: utilities/a11y
|
|
170
173
|
* ---
|
|
171
|
-
*
|
|
172
|
-
* Class for focus operations.
|
|
174
|
+
*
|
|
175
|
+
* Class for focus operations, manages multiple [FocusRegion](#FocusRegion)s.
|
|
173
176
|
* - Scoping focus within a given context,
|
|
174
177
|
* - Mark active element for focus later
|
|
175
178
|
* - Return focus to the marked element
|
|
179
|
+
* @module FocusManager
|
|
176
180
|
*/
|
|
177
181
|
FocusRegionManager };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -28,16 +28,14 @@ import { scopeTab } from './scopeTab';
|
|
|
28
28
|
|
|
29
29
|
class KeyboardFocusRegion {
|
|
30
30
|
constructor(element, options) {
|
|
31
|
-
this.
|
|
31
|
+
this._options = void 0;
|
|
32
32
|
this._focusLaterElement = null;
|
|
33
33
|
this._needToFocus = false;
|
|
34
34
|
this._listeners = [];
|
|
35
35
|
this._raf = [];
|
|
36
36
|
this._active = false;
|
|
37
|
-
|
|
38
|
-
this.
|
|
39
|
-
this._options.onDismiss(event);
|
|
40
|
-
};
|
|
37
|
+
this._wasDocumentClick = void 0;
|
|
38
|
+
this._contextElement = void 0;
|
|
41
39
|
|
|
42
40
|
this.handleKeyDown = event => {
|
|
43
41
|
if (event.keyCode === keycode.codes.tab) {
|
|
@@ -45,11 +43,11 @@ class KeyboardFocusRegion {
|
|
|
45
43
|
}
|
|
46
44
|
};
|
|
47
45
|
|
|
48
|
-
this.handleClick =
|
|
46
|
+
this.handleClick = () => {
|
|
49
47
|
this._wasDocumentClick = true;
|
|
50
48
|
};
|
|
51
49
|
|
|
52
|
-
this.handleWindowBlur =
|
|
50
|
+
this.handleWindowBlur = () => {
|
|
53
51
|
if (this._wasDocumentClick) {
|
|
54
52
|
this._wasDocumentClick = false;
|
|
55
53
|
return;
|
|
@@ -58,7 +56,7 @@ class KeyboardFocusRegion {
|
|
|
58
56
|
this._needToFocus = true;
|
|
59
57
|
};
|
|
60
58
|
|
|
61
|
-
this.handleFocus =
|
|
59
|
+
this.handleFocus = () => {
|
|
62
60
|
if (this._needToFocus) {
|
|
63
61
|
this._needToFocus = false;
|
|
64
62
|
|
|
@@ -83,13 +81,17 @@ class KeyboardFocusRegion {
|
|
|
83
81
|
|
|
84
82
|
this.handleFirstTabbableKeyDown = event => {
|
|
85
83
|
if (event.keyCode === keycode.codes.tab && event.shiftKey) {
|
|
86
|
-
|
|
84
|
+
var _this$_options$onBlur, _this$_options;
|
|
85
|
+
|
|
86
|
+
(_this$_options$onBlur = (_this$_options = this._options).onBlur) === null || _this$_options$onBlur === void 0 ? void 0 : _this$_options$onBlur.call(_this$_options, event);
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
89
|
|
|
90
90
|
this.handleLastTabbableKeyDown = event => {
|
|
91
91
|
if (event.keyCode === keycode.codes.tab && !event.shiftKey) {
|
|
92
|
-
|
|
92
|
+
var _this$_options$onBlur2, _this$_options2;
|
|
93
|
+
|
|
94
|
+
(_this$_options$onBlur2 = (_this$_options2 = this._options).onBlur) === null || _this$_options$onBlur2 === void 0 ? void 0 : _this$_options$onBlur2.call(_this$_options2, event);
|
|
93
95
|
}
|
|
94
96
|
};
|
|
95
97
|
|
|
@@ -97,13 +99,11 @@ class KeyboardFocusRegion {
|
|
|
97
99
|
this._options = options || {
|
|
98
100
|
shouldContainFocus: true,
|
|
99
101
|
shouldReturnFocus: true,
|
|
100
|
-
onBlur: event => {},
|
|
101
|
-
onDismiss: event => {},
|
|
102
102
|
defaultFocusElement: null
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
if (this._options.shouldReturnFocus) {
|
|
106
|
-
this._focusLaterElement = this.
|
|
106
|
+
this._focusLaterElement = getActiveElement(this.doc);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -113,7 +113,7 @@ class KeyboardFocusRegion {
|
|
|
113
113
|
|
|
114
114
|
get shouldContainFocus() {
|
|
115
115
|
const shouldContainFocus = this._options.shouldContainFocus;
|
|
116
|
-
return shouldContainFocus === true || Array.isArray(shouldContainFocus) && shouldContainFocus.includes
|
|
116
|
+
return shouldContainFocus === true || Array.isArray(shouldContainFocus) && shouldContainFocus.includes('keyboard');
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
get focusable() {
|
|
@@ -148,10 +148,6 @@ class KeyboardFocusRegion {
|
|
|
148
148
|
return ownerWindow(this._contextElement);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
get activeElement() {
|
|
152
|
-
return getActiveElement(this.doc);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
151
|
get defaultFocusElement() {
|
|
156
152
|
const defaultFocusElement = this._options.defaultFocusElement;
|
|
157
153
|
const element = findDOMNode(typeof defaultFocusElement === 'function' ? defaultFocusElement() : defaultFocusElement);
|
|
@@ -160,10 +156,8 @@ class KeyboardFocusRegion {
|
|
|
160
156
|
return element;
|
|
161
157
|
}
|
|
162
158
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (firstTabbable) {
|
|
166
|
-
return firstTabbable;
|
|
159
|
+
if (this.firstTabbable) {
|
|
160
|
+
return this.firstTabbable;
|
|
167
161
|
}
|
|
168
162
|
|
|
169
163
|
if (this._contextElement && this.focusable.includes(this._contextElement)) {
|
|
@@ -178,20 +172,17 @@ class KeyboardFocusRegion {
|
|
|
178
172
|
}
|
|
179
173
|
|
|
180
174
|
focusDefaultElement() {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (defaultFocusElement) {
|
|
186
|
-
defaultFocusElement.focus();
|
|
175
|
+
if (this.defaultFocusElement) {
|
|
176
|
+
;
|
|
177
|
+
this.defaultFocusElement.focus();
|
|
187
178
|
} else {
|
|
188
|
-
if (shouldContainFocus) {
|
|
179
|
+
if (this.shouldContainFocus) {
|
|
189
180
|
// Blur the active element to place focus on the document body
|
|
190
|
-
|
|
181
|
+
getActiveElement(this.doc) && getActiveElement(this.doc).blur();
|
|
191
182
|
error(true, `
|
|
192
|
-
[KeyboardFocusRegion] No \`defaultFocusElement\` was provided and
|
|
193
|
-
was set to \`true\`. Focus has
|
|
194
|
-
|
|
183
|
+
[KeyboardFocusRegion] No \`defaultFocusElement\` was provided and
|
|
184
|
+
\`shouldContainFocus\` was set to \`true\` or \`keyboard\`. Focus has
|
|
185
|
+
been moved to the document body instead.`);
|
|
195
186
|
}
|
|
196
187
|
}
|
|
197
188
|
}
|
|
@@ -209,6 +200,8 @@ class KeyboardFocusRegion {
|
|
|
209
200
|
blur() {
|
|
210
201
|
if (this._options.shouldReturnFocus && this._focusLaterElement) {
|
|
211
202
|
try {
|
|
203
|
+
;
|
|
204
|
+
|
|
212
205
|
this._focusLaterElement.focus();
|
|
213
206
|
} catch (e) {
|
|
214
207
|
error(false, `
|
|
@@ -257,7 +250,6 @@ class KeyboardFocusRegion {
|
|
|
257
250
|
this._raf.forEach(request => request.cancel());
|
|
258
251
|
|
|
259
252
|
this._raf = [];
|
|
260
|
-
this._preventCloseOnDocumentClick = false;
|
|
261
253
|
this._active = false;
|
|
262
254
|
}
|
|
263
255
|
}
|
|
@@ -270,10 +262,11 @@ export {
|
|
|
270
262
|
* ---
|
|
271
263
|
* category: utilities/a11y
|
|
272
264
|
* ---
|
|
273
|
-
*
|
|
265
|
+
*
|
|
274
266
|
* Class for focus operations.
|
|
275
267
|
* - Scoping focus within a given context (DOM node),
|
|
276
268
|
* - Mark active element for focus later
|
|
277
269
|
* - Return focus to the marked element
|
|
270
|
+
* @module KeyboardFocusRegion
|
|
278
271
|
*/
|
|
279
272
|
KeyboardFocusRegion };
|
|
@@ -28,10 +28,13 @@ class ScreenReaderFocusRegion {
|
|
|
28
28
|
shouldContainFocus: true,
|
|
29
29
|
liveRegion: []
|
|
30
30
|
}) {
|
|
31
|
+
this._parents = [];
|
|
32
|
+
this._nodes = [];
|
|
33
|
+
this._liveRegion = void 0;
|
|
34
|
+
this._contextElement = void 0;
|
|
35
|
+
this._options = void 0;
|
|
31
36
|
this._observer = null;
|
|
32
37
|
this._attributes = [];
|
|
33
|
-
this._nodes = [];
|
|
34
|
-
this._parents = [];
|
|
35
38
|
|
|
36
39
|
this.handleDOMMutation = records => {
|
|
37
40
|
records.forEach(record => {
|
|
@@ -159,8 +162,8 @@ class ScreenReaderFocusRegion {
|
|
|
159
162
|
this._observer = new MutationObserver(this.handleDOMMutation);
|
|
160
163
|
let node = this._contextElement;
|
|
161
164
|
|
|
162
|
-
while (node && node.nodeType ===
|
|
163
|
-
const parent = node.parentElement;
|
|
165
|
+
while (node && node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() !== 'body') {
|
|
166
|
+
const parent = node.parentElement;
|
|
164
167
|
|
|
165
168
|
if (parent) {
|
|
166
169
|
this._parents.push(parent);
|
|
@@ -202,9 +205,10 @@ export {
|
|
|
202
205
|
* ---
|
|
203
206
|
* category: utilities/a11y
|
|
204
207
|
* ---
|
|
205
|
-
*
|
|
208
|
+
*
|
|
206
209
|
* Utility that hides all DOM elements outside of a specified node. Used,
|
|
207
210
|
* for example, in overlay components where we want to restrict the screen
|
|
208
|
-
* readers to the overlay content
|
|
211
|
+
* readers to the overlay content.
|
|
212
|
+
* @module ScreenReaderFocusRegion
|
|
209
213
|
*/
|
|
210
214
|
ScreenReaderFocusRegion };
|
package/lib/FocusRegion.js
CHANGED
|
@@ -13,8 +13,6 @@ var _contains = require("@instructure/ui-dom-utils/lib/contains.js");
|
|
|
13
13
|
|
|
14
14
|
var _addEventListener = require("@instructure/ui-dom-utils/lib/addEventListener.js");
|
|
15
15
|
|
|
16
|
-
var _getFrameDocumentSafe = require("@instructure/ui-dom-utils/lib/getFrameDocumentSafe.js");
|
|
17
|
-
|
|
18
16
|
var _ownerDocument = require("@instructure/ui-dom-utils/lib/ownerDocument.js");
|
|
19
17
|
|
|
20
18
|
var _findTabbable = require("@instructure/ui-dom-utils/lib/findTabbable.js");
|
|
@@ -54,11 +52,17 @@ class FocusRegion {
|
|
|
54
52
|
constructor(element, options) {
|
|
55
53
|
this._contextElement = null;
|
|
56
54
|
this._preventCloseOnDocumentClick = false;
|
|
55
|
+
this._options = void 0;
|
|
56
|
+
this._screenReaderFocusRegion = void 0;
|
|
57
|
+
this._keyboardFocusRegion = void 0;
|
|
58
|
+
this._id = void 0;
|
|
57
59
|
this._listeners = [];
|
|
58
60
|
this._active = false;
|
|
59
61
|
|
|
60
62
|
this.handleDismiss = (event, documentClick) => {
|
|
61
|
-
|
|
63
|
+
var _this$_options$onDism, _this$_options;
|
|
64
|
+
|
|
65
|
+
(_this$_options$onDism = (_this$_options = this._options).onDismiss) === null || _this$_options$onDism === void 0 ? void 0 : _this$_options$onDism.call(_this$_options, event, documentClick);
|
|
62
66
|
};
|
|
63
67
|
|
|
64
68
|
this.captureDocumentClick = event => {
|
|
@@ -80,15 +84,14 @@ class FocusRegion {
|
|
|
80
84
|
};
|
|
81
85
|
|
|
82
86
|
this.handleKeyUp = event => {
|
|
83
|
-
if (this._options.shouldCloseOnEscape && event.keyCode === _keycode.default.codes.
|
|
87
|
+
if (this._options.shouldCloseOnEscape && event.keyCode === _keycode.default.codes.esc && !event.defaultPrevented) {
|
|
84
88
|
this.handleDismiss(event);
|
|
85
89
|
}
|
|
86
90
|
};
|
|
87
91
|
|
|
88
92
|
this._options = options || {
|
|
89
93
|
shouldCloseOnDocumentClick: true,
|
|
90
|
-
shouldCloseOnEscape: true
|
|
91
|
-
onDismiss: event => {}
|
|
94
|
+
shouldCloseOnEscape: true
|
|
92
95
|
};
|
|
93
96
|
this._contextElement = element;
|
|
94
97
|
this._screenReaderFocusRegion = new _ScreenReaderFocusRegion.ScreenReaderFocusRegion(element, options);
|
|
@@ -137,7 +140,7 @@ class FocusRegion {
|
|
|
137
140
|
|
|
138
141
|
Array.from(doc.getElementsByTagName('iframe')).forEach(el => {
|
|
139
142
|
// listen for mouseup events on any iframes in the document
|
|
140
|
-
const frameDoc =
|
|
143
|
+
const frameDoc = el.contentDocument;
|
|
141
144
|
|
|
142
145
|
if (frameDoc) {
|
|
143
146
|
this._listeners.push((0, _addEventListener.addEventListener)(frameDoc, 'mouseup', event => {
|
|
@@ -53,6 +53,8 @@ FocusRegionManager.focusRegion = (element, idOrOptions = {}) => {
|
|
|
53
53
|
} else {
|
|
54
54
|
(0, _console.logError)(false, `[FocusRegionManager] Could not focus region with element: ${element}`);
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
return;
|
|
56
58
|
};
|
|
57
59
|
|
|
58
60
|
FocusRegionManager.activateRegion = (element, options) => {
|
|
@@ -95,9 +97,10 @@ FocusRegionManager.addEntry = (element, options = {}) => {
|
|
|
95
97
|
// If the active region is triggering a new focus region that does not have
|
|
96
98
|
// keyboard focusable content, don't deactivate the active region's keyboard
|
|
97
99
|
// focus region
|
|
98
|
-
region.
|
|
100
|
+
const keyboard = region.focused && !keyboardFocusable ? {
|
|
99
101
|
keyboard: false
|
|
100
|
-
}
|
|
102
|
+
} : void 0;
|
|
103
|
+
region.deactivate(keyboard);
|
|
101
104
|
}
|
|
102
105
|
});
|
|
103
106
|
region.activate();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -56,16 +56,14 @@ var _scopeTab = require("./scopeTab");
|
|
|
56
56
|
*/
|
|
57
57
|
class KeyboardFocusRegion {
|
|
58
58
|
constructor(element, options) {
|
|
59
|
-
this.
|
|
59
|
+
this._options = void 0;
|
|
60
60
|
this._focusLaterElement = null;
|
|
61
61
|
this._needToFocus = false;
|
|
62
62
|
this._listeners = [];
|
|
63
63
|
this._raf = [];
|
|
64
64
|
this._active = false;
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
this._options.onDismiss(event);
|
|
68
|
-
};
|
|
65
|
+
this._wasDocumentClick = void 0;
|
|
66
|
+
this._contextElement = void 0;
|
|
69
67
|
|
|
70
68
|
this.handleKeyDown = event => {
|
|
71
69
|
if (event.keyCode === _keycode.default.codes.tab) {
|
|
@@ -73,11 +71,11 @@ class KeyboardFocusRegion {
|
|
|
73
71
|
}
|
|
74
72
|
};
|
|
75
73
|
|
|
76
|
-
this.handleClick =
|
|
74
|
+
this.handleClick = () => {
|
|
77
75
|
this._wasDocumentClick = true;
|
|
78
76
|
};
|
|
79
77
|
|
|
80
|
-
this.handleWindowBlur =
|
|
78
|
+
this.handleWindowBlur = () => {
|
|
81
79
|
if (this._wasDocumentClick) {
|
|
82
80
|
this._wasDocumentClick = false;
|
|
83
81
|
return;
|
|
@@ -86,7 +84,7 @@ class KeyboardFocusRegion {
|
|
|
86
84
|
this._needToFocus = true;
|
|
87
85
|
};
|
|
88
86
|
|
|
89
|
-
this.handleFocus =
|
|
87
|
+
this.handleFocus = () => {
|
|
90
88
|
if (this._needToFocus) {
|
|
91
89
|
this._needToFocus = false;
|
|
92
90
|
|
|
@@ -111,13 +109,17 @@ class KeyboardFocusRegion {
|
|
|
111
109
|
|
|
112
110
|
this.handleFirstTabbableKeyDown = event => {
|
|
113
111
|
if (event.keyCode === _keycode.default.codes.tab && event.shiftKey) {
|
|
114
|
-
|
|
112
|
+
var _this$_options$onBlur, _this$_options;
|
|
113
|
+
|
|
114
|
+
(_this$_options$onBlur = (_this$_options = this._options).onBlur) === null || _this$_options$onBlur === void 0 ? void 0 : _this$_options$onBlur.call(_this$_options, event);
|
|
115
115
|
}
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
this.handleLastTabbableKeyDown = event => {
|
|
119
119
|
if (event.keyCode === _keycode.default.codes.tab && !event.shiftKey) {
|
|
120
|
-
|
|
120
|
+
var _this$_options$onBlur2, _this$_options2;
|
|
121
|
+
|
|
122
|
+
(_this$_options$onBlur2 = (_this$_options2 = this._options).onBlur) === null || _this$_options$onBlur2 === void 0 ? void 0 : _this$_options$onBlur2.call(_this$_options2, event);
|
|
121
123
|
}
|
|
122
124
|
};
|
|
123
125
|
|
|
@@ -125,13 +127,11 @@ class KeyboardFocusRegion {
|
|
|
125
127
|
this._options = options || {
|
|
126
128
|
shouldContainFocus: true,
|
|
127
129
|
shouldReturnFocus: true,
|
|
128
|
-
onBlur: event => {},
|
|
129
|
-
onDismiss: event => {},
|
|
130
130
|
defaultFocusElement: null
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
if (this._options.shouldReturnFocus) {
|
|
134
|
-
this._focusLaterElement = this.
|
|
134
|
+
this._focusLaterElement = (0, _getActiveElement.getActiveElement)(this.doc);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -141,7 +141,7 @@ class KeyboardFocusRegion {
|
|
|
141
141
|
|
|
142
142
|
get shouldContainFocus() {
|
|
143
143
|
const shouldContainFocus = this._options.shouldContainFocus;
|
|
144
|
-
return shouldContainFocus === true || Array.isArray(shouldContainFocus) && shouldContainFocus.includes
|
|
144
|
+
return shouldContainFocus === true || Array.isArray(shouldContainFocus) && shouldContainFocus.includes('keyboard');
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
get focusable() {
|
|
@@ -176,10 +176,6 @@ class KeyboardFocusRegion {
|
|
|
176
176
|
return (0, _ownerWindow.ownerWindow)(this._contextElement);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
get activeElement() {
|
|
180
|
-
return (0, _getActiveElement.getActiveElement)(this.doc);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
179
|
get defaultFocusElement() {
|
|
184
180
|
const defaultFocusElement = this._options.defaultFocusElement;
|
|
185
181
|
const element = (0, _findDOMNode.findDOMNode)(typeof defaultFocusElement === 'function' ? defaultFocusElement() : defaultFocusElement);
|
|
@@ -188,10 +184,8 @@ class KeyboardFocusRegion {
|
|
|
188
184
|
return element;
|
|
189
185
|
}
|
|
190
186
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (firstTabbable) {
|
|
194
|
-
return firstTabbable;
|
|
187
|
+
if (this.firstTabbable) {
|
|
188
|
+
return this.firstTabbable;
|
|
195
189
|
}
|
|
196
190
|
|
|
197
191
|
if (this._contextElement && this.focusable.includes(this._contextElement)) {
|
|
@@ -206,20 +200,17 @@ class KeyboardFocusRegion {
|
|
|
206
200
|
}
|
|
207
201
|
|
|
208
202
|
focusDefaultElement() {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (defaultFocusElement) {
|
|
214
|
-
defaultFocusElement.focus();
|
|
203
|
+
if (this.defaultFocusElement) {
|
|
204
|
+
;
|
|
205
|
+
this.defaultFocusElement.focus();
|
|
215
206
|
} else {
|
|
216
|
-
if (shouldContainFocus) {
|
|
207
|
+
if (this.shouldContainFocus) {
|
|
217
208
|
// Blur the active element to place focus on the document body
|
|
218
|
-
|
|
209
|
+
(0, _getActiveElement.getActiveElement)(this.doc) && (0, _getActiveElement.getActiveElement)(this.doc).blur();
|
|
219
210
|
(0, _console.logError)(true, `
|
|
220
|
-
[KeyboardFocusRegion] No \`defaultFocusElement\` was provided and
|
|
221
|
-
was set to \`true\`. Focus has
|
|
222
|
-
|
|
211
|
+
[KeyboardFocusRegion] No \`defaultFocusElement\` was provided and
|
|
212
|
+
\`shouldContainFocus\` was set to \`true\` or \`keyboard\`. Focus has
|
|
213
|
+
been moved to the document body instead.`);
|
|
223
214
|
}
|
|
224
215
|
}
|
|
225
216
|
}
|
|
@@ -237,6 +228,8 @@ class KeyboardFocusRegion {
|
|
|
237
228
|
blur() {
|
|
238
229
|
if (this._options.shouldReturnFocus && this._focusLaterElement) {
|
|
239
230
|
try {
|
|
231
|
+
;
|
|
232
|
+
|
|
240
233
|
this._focusLaterElement.focus();
|
|
241
234
|
} catch (e) {
|
|
242
235
|
(0, _console.logError)(false, `
|
|
@@ -285,7 +278,6 @@ class KeyboardFocusRegion {
|
|
|
285
278
|
this._raf.forEach(request => request.cancel());
|
|
286
279
|
|
|
287
280
|
this._raf = [];
|
|
288
|
-
this._preventCloseOnDocumentClick = false;
|
|
289
281
|
this._active = false;
|
|
290
282
|
}
|
|
291
283
|
}
|
|
@@ -35,10 +35,13 @@ class ScreenReaderFocusRegion {
|
|
|
35
35
|
shouldContainFocus: true,
|
|
36
36
|
liveRegion: []
|
|
37
37
|
}) {
|
|
38
|
+
this._parents = [];
|
|
39
|
+
this._nodes = [];
|
|
40
|
+
this._liveRegion = void 0;
|
|
41
|
+
this._contextElement = void 0;
|
|
42
|
+
this._options = void 0;
|
|
38
43
|
this._observer = null;
|
|
39
44
|
this._attributes = [];
|
|
40
|
-
this._nodes = [];
|
|
41
|
-
this._parents = [];
|
|
42
45
|
|
|
43
46
|
this.handleDOMMutation = records => {
|
|
44
47
|
records.forEach(record => {
|
|
@@ -166,8 +169,8 @@ class ScreenReaderFocusRegion {
|
|
|
166
169
|
this._observer = new MutationObserver(this.handleDOMMutation);
|
|
167
170
|
let node = this._contextElement;
|
|
168
171
|
|
|
169
|
-
while (node && node.nodeType ===
|
|
170
|
-
const parent = node.parentElement;
|
|
172
|
+
while (node && node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() !== 'body') {
|
|
173
|
+
const parent = node.parentElement;
|
|
171
174
|
|
|
172
175
|
if (parent) {
|
|
173
176
|
this._parents.push(parent);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-a11y-utils",
|
|
3
|
-
"version": "8.12.
|
|
3
|
+
"version": "8.12.1-snapshot.15+c50fd66e4",
|
|
4
4
|
"description": "A collection of utilities for managing focus and screen reader behavior",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -24,19 +24,19 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@babel/runtime": "^7.13.10",
|
|
27
|
-
"@instructure/console": "8.12.
|
|
28
|
-
"@instructure/ui-a11y-content": "8.12.
|
|
29
|
-
"@instructure/ui-dom-utils": "8.12.
|
|
30
|
-
"@instructure/ui-react-utils": "8.12.
|
|
31
|
-
"@instructure/ui-testable": "8.12.
|
|
32
|
-
"@instructure/uid": "8.12.
|
|
27
|
+
"@instructure/console": "8.12.1-snapshot.15+c50fd66e4",
|
|
28
|
+
"@instructure/ui-a11y-content": "8.12.1-snapshot.15+c50fd66e4",
|
|
29
|
+
"@instructure/ui-dom-utils": "8.12.1-snapshot.15+c50fd66e4",
|
|
30
|
+
"@instructure/ui-react-utils": "8.12.1-snapshot.15+c50fd66e4",
|
|
31
|
+
"@instructure/ui-testable": "8.12.1-snapshot.15+c50fd66e4",
|
|
32
|
+
"@instructure/uid": "8.12.1-snapshot.15+c50fd66e4",
|
|
33
33
|
"keycode": "^2",
|
|
34
34
|
"prop-types": "^15"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@instructure/ui-babel-preset": "8.12.
|
|
38
|
-
"@instructure/ui-color-utils": "8.12.
|
|
39
|
-
"@instructure/ui-test-utils": "8.12.
|
|
37
|
+
"@instructure/ui-babel-preset": "8.12.1-snapshot.15+c50fd66e4",
|
|
38
|
+
"@instructure/ui-color-utils": "8.12.1-snapshot.15+c50fd66e4",
|
|
39
|
+
"@instructure/ui-test-utils": "8.12.1-snapshot.15+c50fd66e4"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": ">=16.8 <=17"
|
|
@@ -44,5 +44,6 @@
|
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
|
-
"sideEffects": false
|
|
47
|
+
"sideEffects": false,
|
|
48
|
+
"gitHead": "c50fd66e4ba9e5d4b814659f8ee4e1cc2f929cc2"
|
|
48
49
|
}
|