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