@khanacademy/wonder-blocks-modal 2.3.5 → 2.3.7

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 CHANGED
@@ -1,5 +1,24 @@
1
1
  # @khanacademy/wonder-blocks-modal
2
2
 
3
+ ## 2.3.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [6ee20af9]
8
+ - @khanacademy/wonder-blocks-core@4.4.0
9
+ - @khanacademy/wonder-blocks-breadcrumbs@1.0.33
10
+ - @khanacademy/wonder-blocks-icon@1.2.30
11
+ - @khanacademy/wonder-blocks-icon-button@3.4.11
12
+ - @khanacademy/wonder-blocks-layout@1.4.11
13
+ - @khanacademy/wonder-blocks-toolbar@2.1.34
14
+ - @khanacademy/wonder-blocks-typography@1.1.33
15
+
16
+ ## 2.3.6
17
+
18
+ ### Patch Changes
19
+
20
+ - 2546b126: Fix the focus trap navigation to be able to work properly in all scenarios
21
+
3
22
  ## 2.3.5
4
23
 
5
24
  ### Patch Changes
package/dist/es/index.js CHANGED
@@ -205,9 +205,10 @@ const styleSheets$2 = {
205
205
  })
206
206
  };
207
207
 
208
+ const FOCUSABLE_ELEMENTS$1 = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
208
209
  class FocusTrap extends React.Component {
209
- constructor(props) {
210
- super(props);
210
+ constructor(...args) {
211
+ super(...args);
211
212
 
212
213
  this.getModalRoot = node => {
213
214
  if (!node) {
@@ -223,87 +224,31 @@ class FocusTrap extends React.Component {
223
224
  this.modalRoot = modalRoot;
224
225
  };
225
226
 
226
- this.handleGlobalFocus = e => {
227
- if (this.ignoreFocusChanges) {
228
- return;
229
- }
230
-
231
- const target = e.target;
232
-
233
- if (!(target instanceof Node)) {
234
- return;
235
- }
236
-
237
- const modalRoot = this.modalRoot;
238
-
239
- if (!modalRoot) {
240
- return;
241
- }
242
-
243
- if (modalRoot.contains(target)) {
244
- this.lastNodeFocusedInModal = target;
245
- } else {
246
- this.focusFirstElementIn(modalRoot);
247
-
248
- if (document.activeElement === this.lastNodeFocusedInModal) {
249
- this.focusLastElementIn(modalRoot);
250
- }
251
-
252
- this.lastNodeFocusedInModal = document.activeElement;
253
- }
227
+ this.handleFocusMoveToLast = () => {
228
+ this.focusElementIn(false);
254
229
  };
255
230
 
256
- this.lastNodeFocusedInModal = null;
257
- this.ignoreFocusChanges = false;
258
- }
259
-
260
- componentDidMount() {
261
- window.addEventListener("focus", this.handleGlobalFocus, true);
262
- }
263
-
264
- componentWillUnmount() {
265
- window.removeEventListener("focus", this.handleGlobalFocus, true);
231
+ this.handleFocusMoveToFirst = () => {
232
+ this.focusElementIn(true);
233
+ };
266
234
  }
267
235
 
268
236
  tryToFocus(node) {
269
237
  if (node instanceof HTMLElement) {
270
- this.ignoreFocusChanges = true;
271
-
272
238
  try {
273
239
  node.focus();
274
240
  } catch (e) {}
275
241
 
276
- this.ignoreFocusChanges = false;
277
242
  return document.activeElement === node;
278
243
  }
279
244
  }
280
245
 
281
- focusFirstElementIn(currentParent) {
282
- const children = currentParent.childNodes;
283
-
284
- for (let i = 0; i < children.length; i++) {
285
- const child = children[i];
286
-
287
- if (this.tryToFocus(child) || this.focusFirstElementIn(child)) {
288
- return true;
289
- }
290
- }
291
-
292
- return false;
293
- }
294
-
295
- focusLastElementIn(currentParent) {
296
- const children = currentParent.childNodes;
297
-
298
- for (let i = children.length - 1; i >= 0; i--) {
299
- const child = children[i];
300
-
301
- if (this.tryToFocus(child) || this.focusLastElementIn(child)) {
302
- return true;
303
- }
304
- }
305
-
306
- return false;
246
+ focusElementIn(isLast) {
247
+ const modalRootAsHtmlEl = this.modalRoot;
248
+ const focusableNodes = Array.from(modalRootAsHtmlEl.querySelectorAll(FOCUSABLE_ELEMENTS$1));
249
+ const nodeIndex = !isLast ? focusableNodes.length - 1 : 0;
250
+ const focusableNode = focusableNodes[nodeIndex];
251
+ this.tryToFocus(focusableNode);
307
252
  }
308
253
 
309
254
  render() {
@@ -312,6 +257,8 @@ class FocusTrap extends React.Component {
312
257
  } = this.props;
313
258
  return React.createElement(React.Fragment, null, React.createElement("div", {
314
259
  tabIndex: "0",
260
+ className: "modal-focus-trap-first",
261
+ onFocus: this.handleFocusMoveToLast,
315
262
  style: {
316
263
  position: "fixed"
317
264
  }
@@ -320,6 +267,8 @@ class FocusTrap extends React.Component {
320
267
  ref: this.getModalRoot
321
268
  }, this.props.children), React.createElement("div", {
322
269
  tabIndex: "0",
270
+ className: "modal-focus-trap-last",
271
+ onFocus: this.handleFocusMoveToFirst,
323
272
  style: {
324
273
  position: "fixed"
325
274
  }