focus-trap 7.0.0 → 7.1.0

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.
@@ -1,22 +1,19 @@
1
1
  /*!
2
- * focus-trap 7.0.0
2
+ * focus-trap 7.1.0
3
3
  * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
4
4
  */
5
5
  import { tabbable, focusable, isTabbable, isFocusable } from 'tabbable';
6
6
 
7
7
  function ownKeys(object, enumerableOnly) {
8
8
  var keys = Object.keys(object);
9
-
10
9
  if (Object.getOwnPropertySymbols) {
11
10
  var symbols = Object.getOwnPropertySymbols(object);
12
11
  enumerableOnly && (symbols = symbols.filter(function (sym) {
13
12
  return Object.getOwnPropertyDescriptor(object, sym).enumerable;
14
13
  })), keys.push.apply(keys, symbols);
15
14
  }
16
-
17
15
  return keys;
18
16
  }
19
-
20
17
  function _objectSpread2(target) {
21
18
  for (var i = 1; i < arguments.length; i++) {
22
19
  var source = null != arguments[i] ? arguments[i] : {};
@@ -26,10 +23,8 @@ function _objectSpread2(target) {
26
23
  Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
27
24
  });
28
25
  }
29
-
30
26
  return target;
31
27
  }
32
-
33
28
  function _defineProperty(obj, key, value) {
34
29
  if (key in obj) {
35
30
  Object.defineProperty(obj, key, {
@@ -41,64 +36,52 @@ function _defineProperty(obj, key, value) {
41
36
  } else {
42
37
  obj[key] = value;
43
38
  }
44
-
45
39
  return obj;
46
40
  }
47
41
 
48
- var activeFocusTraps = function () {
49
- var trapQueue = [];
50
- return {
51
- activateTrap: function activateTrap(trap) {
52
- if (trapQueue.length > 0) {
53
- var activeTrap = trapQueue[trapQueue.length - 1];
54
-
55
- if (activeTrap !== trap) {
56
- activeTrap.pause();
57
- }
58
- }
59
-
60
- var trapIndex = trapQueue.indexOf(trap);
61
-
62
- if (trapIndex === -1) {
63
- trapQueue.push(trap);
64
- } else {
65
- // move this existing trap to the front of the queue
66
- trapQueue.splice(trapIndex, 1);
67
- trapQueue.push(trap);
68
- }
69
- },
70
- deactivateTrap: function deactivateTrap(trap) {
71
- var trapIndex = trapQueue.indexOf(trap);
72
-
73
- if (trapIndex !== -1) {
74
- trapQueue.splice(trapIndex, 1);
75
- }
76
-
77
- if (trapQueue.length > 0) {
78
- trapQueue[trapQueue.length - 1].unpause();
42
+ var rooTrapStack = [];
43
+ var activeFocusTraps = {
44
+ activateTrap: function activateTrap(trapStack, trap) {
45
+ if (trapStack.length > 0) {
46
+ var activeTrap = trapStack[trapStack.length - 1];
47
+ if (activeTrap !== trap) {
48
+ activeTrap.pause();
79
49
  }
80
50
  }
81
- };
82
- }();
83
-
51
+ var trapIndex = trapStack.indexOf(trap);
52
+ if (trapIndex === -1) {
53
+ trapStack.push(trap);
54
+ } else {
55
+ // move this existing trap to the front of the queue
56
+ trapStack.splice(trapIndex, 1);
57
+ trapStack.push(trap);
58
+ }
59
+ },
60
+ deactivateTrap: function deactivateTrap(trapStack, trap) {
61
+ var trapIndex = trapStack.indexOf(trap);
62
+ if (trapIndex !== -1) {
63
+ trapStack.splice(trapIndex, 1);
64
+ }
65
+ if (trapStack.length > 0) {
66
+ trapStack[trapStack.length - 1].unpause();
67
+ }
68
+ }
69
+ };
84
70
  var isSelectableInput = function isSelectableInput(node) {
85
71
  return node.tagName && node.tagName.toLowerCase() === 'input' && typeof node.select === 'function';
86
72
  };
87
-
88
73
  var isEscapeEvent = function isEscapeEvent(e) {
89
74
  return e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27;
90
75
  };
91
-
92
76
  var isTabEvent = function isTabEvent(e) {
93
77
  return e.key === 'Tab' || e.keyCode === 9;
94
78
  };
95
-
96
79
  var delay = function delay(fn) {
97
80
  return setTimeout(fn, 0);
98
- }; // Array.find/findIndex() are not supported on IE; this replicates enough
99
- // of Array.findIndex() for our needs
100
-
81
+ };
101
82
 
83
+ // Array.find/findIndex() are not supported on IE; this replicates enough
84
+ // of Array.findIndex() for our needs
102
85
  var findIndex = function findIndex(arr, fn) {
103
86
  var idx = -1;
104
87
  arr.every(function (value, i) {
@@ -109,8 +92,10 @@ var findIndex = function findIndex(arr, fn) {
109
92
 
110
93
  return true; // next
111
94
  });
95
+
112
96
  return idx;
113
97
  };
98
+
114
99
  /**
115
100
  * Get an option's value when it could be a plain value, or a handler that provides
116
101
  * the value.
@@ -118,16 +103,12 @@ var findIndex = function findIndex(arr, fn) {
118
103
  * @param {...*} [params] Any parameters to pass to the handler, if `value` is a function.
119
104
  * @returns {*} The `value`, or the handler's returned value.
120
105
  */
121
-
122
-
123
106
  var valueOrHandler = function valueOrHandler(value) {
124
107
  for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
125
108
  params[_key - 1] = arguments[_key];
126
109
  }
127
-
128
110
  return typeof value === 'function' ? value.apply(void 0, params) : value;
129
111
  };
130
-
131
112
  var getActualTarget = function getActualTarget(event) {
132
113
  // NOTE: If the trap is _inside_ a shadow DOM, event.target will always be the
133
114
  // shadow host. However, event.target.composedPath() will be an array of
@@ -138,18 +119,16 @@ var getActualTarget = function getActualTarget(event) {
138
119
  // composedPath()[0] === event.target always).
139
120
  return event.target.shadowRoot && typeof event.composedPath === 'function' ? event.composedPath()[0] : event.target;
140
121
  };
141
-
142
122
  var createFocusTrap = function createFocusTrap(elements, userOptions) {
143
123
  // SSR: a live trap shouldn't be created in this type of environment so this
144
124
  // should be safe code to execute if the `document` option isn't specified
145
125
  var doc = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.document) || document;
146
-
126
+ var trapStack = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.trapStack) || rooTrapStack;
147
127
  var config = _objectSpread2({
148
128
  returnFocusOnDeactivate: true,
149
129
  escapeDeactivates: true,
150
130
  delayInitialFocus: true
151
131
  }, userOptions);
152
-
153
132
  var state = {
154
133
  // containers given to createFocusTrap()
155
134
  // @type {Array<HTMLElement>}
@@ -169,6 +148,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
169
148
  // }>}
170
149
  containerGroups: [],
171
150
  // same order/length as `containers` list
151
+
172
152
  // references to objects in `containerGroups`, but only those that actually have
173
153
  // tabbable nodes in them
174
154
  // NOTE: same order as `containers` and `containerGroups`, but __not necessarily__
@@ -192,10 +172,10 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
192
172
  * @param {string|undefined} [configOptionName] Name of option to use __instead of__ `optionName`
193
173
  * IIF `configOverrideOptions` is not defined. Otherwise, `optionName` is used.
194
174
  */
195
-
196
175
  var getOption = function getOption(configOverrideOptions, optionName, configOptionName) {
197
176
  return configOverrideOptions && configOverrideOptions[optionName] !== undefined ? configOverrideOptions[optionName] : config[configOptionName || optionName];
198
177
  };
178
+
199
179
  /**
200
180
  * Finds the index of the container that contains the element.
201
181
  * @param {HTMLElement} element
@@ -203,16 +183,15 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
203
183
  * `state.containerGroups` (the order/length of these lists are the same); -1
204
184
  * if the element isn't found.
205
185
  */
206
-
207
-
208
186
  var findContainerIndex = function findContainerIndex(element) {
209
187
  // NOTE: search `containerGroups` because it's possible a group contains no tabbable
210
188
  // nodes, but still contains focusable nodes (e.g. if they all have `tabindex=-1`)
211
189
  // and we still need to find the element in there
212
190
  return state.containerGroups.findIndex(function (_ref) {
213
191
  var container = _ref.container,
214
- tabbableNodes = _ref.tabbableNodes;
215
- return container.contains(element) || // fall back to explicit tabbable search which will take into consideration any
192
+ tabbableNodes = _ref.tabbableNodes;
193
+ return container.contains(element) ||
194
+ // fall back to explicit tabbable search which will take into consideration any
216
195
  // web components if the `tabbableOptions.getShadowRoot` option was used for
217
196
  // the trap, enabling shadow DOM support in tabbable (`Node.contains()` doesn't
218
197
  // look inside web components even if open)
@@ -221,6 +200,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
221
200
  });
222
201
  });
223
202
  };
203
+
224
204
  /**
225
205
  * Gets the node for the given option, which is expected to be an option that
226
206
  * can be either a DOM node, a string that is a selector to get a node, `false`
@@ -234,19 +214,14 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
234
214
  * @throws {Error} If the option is set, not `false`, and is not, or does not
235
215
  * resolve to a node.
236
216
  */
237
-
238
-
239
217
  var getNodeForOption = function getNodeForOption(optionName) {
240
218
  var optionValue = config[optionName];
241
-
242
219
  if (typeof optionValue === 'function') {
243
220
  for (var _len2 = arguments.length, params = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
244
221
  params[_key2 - 1] = arguments[_key2];
245
222
  }
246
-
247
223
  optionValue = optionValue.apply(void 0, params);
248
224
  }
249
-
250
225
  if (optionValue === true) {
251
226
  optionValue = undefined; // use default value
252
227
  }
@@ -254,56 +229,51 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
254
229
  if (!optionValue) {
255
230
  if (optionValue === undefined || optionValue === false) {
256
231
  return optionValue;
257
- } // else, empty string (invalid), null (invalid), 0 (invalid)
258
-
232
+ }
233
+ // else, empty string (invalid), null (invalid), 0 (invalid)
259
234
 
260
235
  throw new Error("`".concat(optionName, "` was specified but was not a node, or did not return a node"));
261
236
  }
262
-
263
237
  var node = optionValue; // could be HTMLElement, SVGElement, or non-empty string at this point
264
238
 
265
239
  if (typeof optionValue === 'string') {
266
240
  node = doc.querySelector(optionValue); // resolve to node, or null if fails
267
-
268
241
  if (!node) {
269
242
  throw new Error("`".concat(optionName, "` as selector refers to no known node"));
270
243
  }
271
244
  }
272
-
273
245
  return node;
274
246
  };
275
-
276
247
  var getInitialFocusNode = function getInitialFocusNode() {
277
- var node = getNodeForOption('initialFocus'); // false explicitly indicates we want no initialFocus at all
248
+ var node = getNodeForOption('initialFocus');
278
249
 
250
+ // false explicitly indicates we want no initialFocus at all
279
251
  if (node === false) {
280
252
  return false;
281
253
  }
282
-
283
254
  if (node === undefined) {
284
255
  // option not specified: use fallback options
285
256
  if (findContainerIndex(doc.activeElement) >= 0) {
286
257
  node = doc.activeElement;
287
258
  } else {
288
259
  var firstTabbableGroup = state.tabbableGroups[0];
289
- var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode; // NOTE: `fallbackFocus` option function cannot return `false` (not supported)
260
+ var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
290
261
 
262
+ // NOTE: `fallbackFocus` option function cannot return `false` (not supported)
291
263
  node = firstTabbableNode || getNodeForOption('fallbackFocus');
292
264
  }
293
265
  }
294
-
295
266
  if (!node) {
296
267
  throw new Error('Your focus-trap needs to have at least one focusable element');
297
268
  }
298
-
299
269
  return node;
300
270
  };
301
-
302
271
  var updateTabbableNodes = function updateTabbableNodes() {
303
272
  state.containerGroups = state.containers.map(function (container) {
304
- var tabbableNodes = tabbable(container, config.tabbableOptions); // NOTE: if we have tabbable nodes, we must have focusable nodes; focusable nodes
305
- // are a superset of tabbable nodes
273
+ var tabbableNodes = tabbable(container, config.tabbableOptions);
306
274
 
275
+ // NOTE: if we have tabbable nodes, we must have focusable nodes; focusable nodes
276
+ // are a superset of tabbable nodes
307
277
  var focusableNodes = focusable(container, config.tabbableOptions);
308
278
  return {
309
279
  container: container,
@@ -311,7 +281,6 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
311
281
  focusableNodes: focusableNodes,
312
282
  firstTabbableNode: tabbableNodes.length > 0 ? tabbableNodes[0] : null,
313
283
  lastTabbableNode: tabbableNodes.length > 0 ? tabbableNodes[tabbableNodes.length - 1] : null,
314
-
315
284
  /**
316
285
  * Finds the __tabbable__ node that follows the given node in the specified direction,
317
286
  * in this container, if any.
@@ -335,17 +304,14 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
335
304
  var nodeIdx = focusableNodes.findIndex(function (n) {
336
305
  return n === node;
337
306
  });
338
-
339
307
  if (nodeIdx < 0) {
340
308
  return undefined;
341
309
  }
342
-
343
310
  if (forward) {
344
311
  return focusableNodes.slice(nodeIdx + 1).find(function (n) {
345
312
  return isTabbable(n, config.tabbableOptions);
346
313
  });
347
314
  }
348
-
349
315
  return focusableNodes.slice(0, nodeIdx).reverse().find(function (n) {
350
316
  return isTabbable(n, config.tabbableOptions);
351
317
  });
@@ -354,53 +320,46 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
354
320
  });
355
321
  state.tabbableGroups = state.containerGroups.filter(function (group) {
356
322
  return group.tabbableNodes.length > 0;
357
- }); // throw if no groups have tabbable nodes and we don't have a fallback focus node either
323
+ });
358
324
 
325
+ // throw if no groups have tabbable nodes and we don't have a fallback focus node either
359
326
  if (state.tabbableGroups.length <= 0 && !getNodeForOption('fallbackFocus') // returning false not supported for this option
360
327
  ) {
361
328
  throw new Error('Your focus-trap must have at least one container with at least one tabbable node in it at all times');
362
329
  }
363
330
  };
364
-
365
331
  var tryFocus = function tryFocus(node) {
366
332
  if (node === false) {
367
333
  return;
368
334
  }
369
-
370
335
  if (node === doc.activeElement) {
371
336
  return;
372
337
  }
373
-
374
338
  if (!node || !node.focus) {
375
339
  tryFocus(getInitialFocusNode());
376
340
  return;
377
341
  }
378
-
379
342
  node.focus({
380
343
  preventScroll: !!config.preventScroll
381
344
  });
382
345
  state.mostRecentlyFocusedNode = node;
383
-
384
346
  if (isSelectableInput(node)) {
385
347
  node.select();
386
348
  }
387
349
  };
388
-
389
350
  var getReturnFocusNode = function getReturnFocusNode(previousActiveElement) {
390
351
  var node = getNodeForOption('setReturnFocus', previousActiveElement);
391
352
  return node ? node : node === false ? false : previousActiveElement;
392
- }; // This needs to be done on mousedown and touchstart instead of click
393
- // so that it precedes the focus event.
394
-
353
+ };
395
354
 
355
+ // This needs to be done on mousedown and touchstart instead of click
356
+ // so that it precedes the focus event.
396
357
  var checkPointerDown = function checkPointerDown(e) {
397
358
  var target = getActualTarget(e);
398
-
399
359
  if (findContainerIndex(target) >= 0) {
400
360
  // allow the click since it ocurred inside the trap
401
361
  return;
402
362
  }
403
-
404
363
  if (valueOrHandler(config.clickOutsideDeactivates, e)) {
405
364
  // immediately deactivate the trap
406
365
  trap.deactivate({
@@ -418,25 +377,26 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
418
377
  returnFocus: config.returnFocusOnDeactivate && !isFocusable(target, config.tabbableOptions)
419
378
  });
420
379
  return;
421
- } // This is needed for mobile devices.
380
+ }
381
+
382
+ // This is needed for mobile devices.
422
383
  // (If we'll only let `click` events through,
423
384
  // then on mobile they will be blocked anyways if `touchstart` is blocked.)
424
-
425
-
426
385
  if (valueOrHandler(config.allowOutsideClick, e)) {
427
386
  // allow the click outside the trap to take place
428
387
  return;
429
- } // otherwise, prevent the click
430
-
388
+ }
431
389
 
390
+ // otherwise, prevent the click
432
391
  e.preventDefault();
433
- }; // In case focus escapes the trap for some strange reason, pull it back in.
434
-
392
+ };
435
393
 
394
+ // In case focus escapes the trap for some strange reason, pull it back in.
436
395
  var checkFocusIn = function checkFocusIn(e) {
437
396
  var target = getActualTarget(e);
438
- var targetContained = findContainerIndex(target) >= 0; // In Firefox when you Tab out of an iframe the Document is briefly focused.
397
+ var targetContained = findContainerIndex(target) >= 0;
439
398
 
399
+ // In Firefox when you Tab out of an iframe the Document is briefly focused.
440
400
  if (targetContained || target instanceof Document) {
441
401
  if (targetContained) {
442
402
  state.mostRecentlyFocusedNode = target;
@@ -446,24 +406,22 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
446
406
  e.stopImmediatePropagation();
447
407
  tryFocus(state.mostRecentlyFocusedNode || getInitialFocusNode());
448
408
  }
449
- }; // Hijack Tab events on the first and last focusable nodes of the trap,
409
+ };
410
+
411
+ // Hijack Tab events on the first and last focusable nodes of the trap,
450
412
  // in order to prevent focus from escaping. If it escapes for even a
451
413
  // moment it can end up scrolling the page and causing confusion so we
452
414
  // kind of need to capture the action at the keydown phase.
453
-
454
-
455
415
  var checkTab = function checkTab(e) {
456
416
  var target = getActualTarget(e);
457
417
  updateTabbableNodes();
458
418
  var destinationNode = null;
459
-
460
419
  if (state.tabbableGroups.length > 0) {
461
420
  // make sure the target is actually contained in a group
462
421
  // NOTE: the target may also be the container itself if it's focusable
463
422
  // with tabIndex='-1' and was given initial focus
464
423
  var containerIndex = findContainerIndex(target);
465
424
  var containerGroup = containerIndex >= 0 ? state.containerGroups[containerIndex] : undefined;
466
-
467
425
  if (containerIndex < 0) {
468
426
  // target not found in any group: quite possible focus has escaped the trap,
469
427
  // so bring it back in to...
@@ -476,12 +434,12 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
476
434
  }
477
435
  } else if (e.shiftKey) {
478
436
  // REVERSE
437
+
479
438
  // is the target the first tabbable node in a group?
480
439
  var startOfGroupIndex = findIndex(state.tabbableGroups, function (_ref2) {
481
440
  var firstTabbableNode = _ref2.firstTabbableNode;
482
441
  return target === firstTabbableNode;
483
442
  });
484
-
485
443
  if (startOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target, false))) {
486
444
  // an exception case where the target is either the container itself, or
487
445
  // a non-tabbable node that was given focus (i.e. tabindex is negative
@@ -491,7 +449,6 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
491
449
  // first tabbable node, and go to the last tabbable node of the LAST group
492
450
  startOfGroupIndex = containerIndex;
493
451
  }
494
-
495
452
  if (startOfGroupIndex >= 0) {
496
453
  // YES: then shift+tab should go to the last tabbable node in the
497
454
  // previous group (and wrap around to the last tabbable node of
@@ -502,12 +459,12 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
502
459
  }
503
460
  } else {
504
461
  // FORWARD
462
+
505
463
  // is the target the last tabbable node in a group?
506
464
  var lastOfGroupIndex = findIndex(state.tabbableGroups, function (_ref3) {
507
465
  var lastTabbableNode = _ref3.lastTabbableNode;
508
466
  return target === lastTabbableNode;
509
467
  });
510
-
511
468
  if (lastOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target))) {
512
469
  // an exception case where the target is the container itself, or
513
470
  // a non-tabbable node that was given focus (i.e. tabindex is negative
@@ -517,13 +474,11 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
517
474
  // last tabbable node, and go to the first tabbable node of the FIRST group
518
475
  lastOfGroupIndex = containerIndex;
519
476
  }
520
-
521
477
  if (lastOfGroupIndex >= 0) {
522
478
  // YES: then tab should go to the first tabbable node in the next
523
479
  // group (and wrap around to the first tabbable node of the FIRST
524
480
  // group if it's the last tabbable node of the LAST group)
525
481
  var _destinationGroupIndex = lastOfGroupIndex === state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
526
-
527
482
  var _destinationGroup = state.tabbableGroups[_destinationGroupIndex];
528
483
  destinationNode = _destinationGroup.firstTabbableNode;
529
484
  }
@@ -532,12 +487,11 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
532
487
  // NOTE: the fallbackFocus option does not support returning false to opt-out
533
488
  destinationNode = getNodeForOption('fallbackFocus');
534
489
  }
535
-
536
490
  if (destinationNode) {
537
491
  e.preventDefault();
538
492
  tryFocus(destinationNode);
539
- } // else, let the browser take care of [shift+]tab and move the focus
540
-
493
+ }
494
+ // else, let the browser take care of [shift+]tab and move the focus
541
495
  };
542
496
 
543
497
  var checkKey = function checkKey(e) {
@@ -546,44 +500,40 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
546
500
  trap.deactivate();
547
501
  return;
548
502
  }
549
-
550
503
  if (isTabEvent(e)) {
551
504
  checkTab(e);
552
505
  return;
553
506
  }
554
507
  };
555
-
556
508
  var checkClick = function checkClick(e) {
557
509
  var target = getActualTarget(e);
558
-
559
510
  if (findContainerIndex(target) >= 0) {
560
511
  return;
561
512
  }
562
-
563
513
  if (valueOrHandler(config.clickOutsideDeactivates, e)) {
564
514
  return;
565
515
  }
566
-
567
516
  if (valueOrHandler(config.allowOutsideClick, e)) {
568
517
  return;
569
518
  }
570
-
571
519
  e.preventDefault();
572
520
  e.stopImmediatePropagation();
573
- }; //
521
+ };
522
+
523
+ //
574
524
  // EVENT LISTENERS
575
525
  //
576
526
 
577
-
578
527
  var addListeners = function addListeners() {
579
528
  if (!state.active) {
580
529
  return;
581
- } // There can be only one listening focus trap at a time
530
+ }
582
531
 
532
+ // There can be only one listening focus trap at a time
533
+ activeFocusTraps.activateTrap(trapStack, trap);
583
534
 
584
- activeFocusTraps.activateTrap(trap); // Delay ensures that the focused element doesn't capture the event
535
+ // Delay ensures that the focused element doesn't capture the event
585
536
  // that caused the focus trap activation.
586
-
587
537
  state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function () {
588
538
  tryFocus(getInitialFocusNode());
589
539
  }) : tryFocus(getInitialFocusNode());
@@ -606,70 +556,58 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
606
556
  });
607
557
  return trap;
608
558
  };
609
-
610
559
  var removeListeners = function removeListeners() {
611
560
  if (!state.active) {
612
561
  return;
613
562
  }
614
-
615
563
  doc.removeEventListener('focusin', checkFocusIn, true);
616
564
  doc.removeEventListener('mousedown', checkPointerDown, true);
617
565
  doc.removeEventListener('touchstart', checkPointerDown, true);
618
566
  doc.removeEventListener('click', checkClick, true);
619
567
  doc.removeEventListener('keydown', checkKey, true);
620
568
  return trap;
621
- }; //
569
+ };
570
+
571
+ //
622
572
  // TRAP DEFINITION
623
573
  //
624
574
 
625
-
626
575
  trap = {
627
576
  get active() {
628
577
  return state.active;
629
578
  },
630
-
631
579
  get paused() {
632
580
  return state.paused;
633
581
  },
634
-
635
582
  activate: function activate(activateOptions) {
636
583
  if (state.active) {
637
584
  return this;
638
585
  }
639
-
640
586
  var onActivate = getOption(activateOptions, 'onActivate');
641
587
  var onPostActivate = getOption(activateOptions, 'onPostActivate');
642
588
  var checkCanFocusTrap = getOption(activateOptions, 'checkCanFocusTrap');
643
-
644
589
  if (!checkCanFocusTrap) {
645
590
  updateTabbableNodes();
646
591
  }
647
-
648
592
  state.active = true;
649
593
  state.paused = false;
650
594
  state.nodeFocusedBeforeActivation = doc.activeElement;
651
-
652
595
  if (onActivate) {
653
596
  onActivate();
654
597
  }
655
-
656
598
  var finishActivation = function finishActivation() {
657
599
  if (checkCanFocusTrap) {
658
600
  updateTabbableNodes();
659
601
  }
660
-
661
602
  addListeners();
662
-
663
603
  if (onPostActivate) {
664
604
  onPostActivate();
665
605
  }
666
606
  };
667
-
668
607
  if (checkCanFocusTrap) {
669
608
  checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
670
609
  return this;
671
610
  }
672
-
673
611
  finishActivation();
674
612
  return this;
675
613
  },
@@ -677,46 +615,38 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
677
615
  if (!state.active) {
678
616
  return this;
679
617
  }
680
-
681
618
  var options = _objectSpread2({
682
619
  onDeactivate: config.onDeactivate,
683
620
  onPostDeactivate: config.onPostDeactivate,
684
621
  checkCanReturnFocus: config.checkCanReturnFocus
685
622
  }, deactivateOptions);
686
-
687
623
  clearTimeout(state.delayInitialFocusTimer); // noop if undefined
688
-
689
624
  state.delayInitialFocusTimer = undefined;
690
625
  removeListeners();
691
626
  state.active = false;
692
627
  state.paused = false;
693
- activeFocusTraps.deactivateTrap(trap);
628
+ activeFocusTraps.deactivateTrap(trapStack, trap);
694
629
  var onDeactivate = getOption(options, 'onDeactivate');
695
630
  var onPostDeactivate = getOption(options, 'onPostDeactivate');
696
631
  var checkCanReturnFocus = getOption(options, 'checkCanReturnFocus');
697
632
  var returnFocus = getOption(options, 'returnFocus', 'returnFocusOnDeactivate');
698
-
699
633
  if (onDeactivate) {
700
634
  onDeactivate();
701
635
  }
702
-
703
636
  var finishDeactivation = function finishDeactivation() {
704
637
  delay(function () {
705
638
  if (returnFocus) {
706
639
  tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
707
640
  }
708
-
709
641
  if (onPostDeactivate) {
710
642
  onPostDeactivate();
711
643
  }
712
644
  });
713
645
  };
714
-
715
646
  if (returnFocus && checkCanReturnFocus) {
716
647
  checkCanReturnFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
717
648
  return this;
718
649
  }
719
-
720
650
  finishDeactivation();
721
651
  return this;
722
652
  },
@@ -724,7 +654,6 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
724
654
  if (state.paused || !state.active) {
725
655
  return this;
726
656
  }
727
-
728
657
  state.paused = true;
729
658
  removeListeners();
730
659
  return this;
@@ -733,7 +662,6 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
733
662
  if (!state.paused || !state.active) {
734
663
  return this;
735
664
  }
736
-
737
665
  state.paused = false;
738
666
  updateTabbableNodes();
739
667
  addListeners();
@@ -744,15 +672,14 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
744
672
  state.containers = elementsAsArray.map(function (element) {
745
673
  return typeof element === 'string' ? doc.querySelector(element) : element;
746
674
  });
747
-
748
675
  if (state.active) {
749
676
  updateTabbableNodes();
750
677
  }
751
-
752
678
  return this;
753
679
  }
754
- }; // initialize container elements
680
+ };
755
681
 
682
+ // initialize container elements
756
683
  trap.updateContainerElements(elements);
757
684
  return trap;
758
685
  };