@dso-toolkit/core 52.0.3 → 53.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.
Files changed (163) hide show
  1. package/dist/cjs/dso-accordion-section.cjs.entry.js +39 -1404
  2. package/dist/cjs/dso-action-list-item.cjs.entry.js +27 -0
  3. package/dist/cjs/dso-action-list.cjs.entry.js +20 -0
  4. package/dist/cjs/dso-annotation-output.cjs.entry.js +1 -1
  5. package/dist/cjs/dso-card-container.cjs.entry.js +1 -1
  6. package/dist/cjs/dso-date-picker.cjs.entry.js +1 -1
  7. package/dist/cjs/dso-dropdown-menu.cjs.entry.js +18 -3
  8. package/dist/cjs/dso-expandable-heading.cjs.entry.js +6 -2
  9. package/dist/cjs/dso-expandable.cjs.entry.js +1433 -2
  10. package/dist/cjs/dso-header.cjs.entry.js +16 -1
  11. package/dist/cjs/dso-helpcenter-panel.cjs.entry.js +2 -2
  12. package/dist/cjs/dso-image-overlay.cjs.entry.js +2 -2
  13. package/dist/cjs/dso-info_2.cjs.entry.js +3 -2
  14. package/dist/cjs/dso-label.cjs.entry.js +1 -8
  15. package/dist/cjs/dso-list-button.cjs.entry.js +3 -3
  16. package/dist/cjs/dso-modal.cjs.entry.js +2 -2
  17. package/dist/cjs/dso-ozon-content.cjs.entry.js +2 -2
  18. package/dist/cjs/dso-table.cjs.entry.js +2 -2
  19. package/dist/cjs/dso-toolkit.cjs.js +1 -1
  20. package/dist/cjs/dso-tooltip.cjs.entry.js +14 -12
  21. package/dist/cjs/dso-viewer-grid.cjs.entry.js +2 -2
  22. package/dist/cjs/expandable.interfaces-19b608b9.js +7 -0
  23. package/dist/cjs/{focus-trap.esm-c501d382.js → focus-trap.esm-a5b7273f.js} +134 -51
  24. package/dist/cjs/{has-overflow-b1b4f3f3.js → has-overflow-dd552ec8.js} +3 -4
  25. package/dist/cjs/index.cjs.js +67 -0
  26. package/dist/cjs/{index.esm-03a9e0b4.js → index.esm-0e935715.js} +97 -17
  27. package/dist/cjs/loader.cjs.js +1 -1
  28. package/dist/collection/collection-manifest.json +3 -1
  29. package/dist/collection/components/accordion/accordion.js +1 -1
  30. package/dist/collection/components/accordion/components/accordion-section.css +60 -10
  31. package/dist/collection/components/accordion/components/accordion-section.js +41 -100
  32. package/dist/collection/components/action-list/action-list.css +25 -0
  33. package/dist/collection/components/action-list/action-list.js +42 -0
  34. package/dist/collection/components/action-list/components/action-list-item.css +81 -0
  35. package/dist/collection/components/action-list/components/action-list-item.js +120 -0
  36. package/dist/collection/components/annotation-output/annotation-output.js +1 -1
  37. package/dist/collection/components/card-container/card-container.css +15 -1
  38. package/dist/collection/components/date-picker/date-picker.css +1 -1
  39. package/dist/collection/components/date-picker/date-picker.js +1 -1
  40. package/dist/collection/components/dropdown-menu/dropdown-menu.js +36 -1
  41. package/dist/collection/components/expandable/expandable.css +12 -1
  42. package/dist/collection/components/expandable/expandable.interfaces.js +3 -0
  43. package/dist/collection/components/expandable/expandable.js +246 -2
  44. package/dist/collection/components/expandable-heading/expandable-heading.css +34 -0
  45. package/dist/collection/components/expandable-heading/expandable-heading.js +28 -2
  46. package/dist/collection/components/header/header.js +18 -2
  47. package/dist/collection/components/label/label.js +1 -8
  48. package/dist/collection/components/list-button/list-button.css +2 -2
  49. package/dist/collection/components/modal/modal-ref.js +18 -0
  50. package/dist/collection/components/modal/modal.controller.js +47 -0
  51. package/dist/collection/components/modal/modal.js +3 -7
  52. package/dist/collection/components/ozon-content/ozon-content.css +8 -0
  53. package/dist/collection/components/selectable/selectable.css +22 -9
  54. package/dist/collection/components/selectable/selectable.js +2 -1
  55. package/dist/collection/components/tooltip/tooltip.js +13 -11
  56. package/dist/collection/index.js +2 -0
  57. package/dist/components/dropdown-menu.js +17 -1
  58. package/dist/components/dso-accordion-section.js +52 -1407
  59. package/dist/components/dso-action-list-item.d.ts +11 -0
  60. package/dist/components/dso-action-list-item.js +53 -0
  61. package/dist/components/dso-action-list.d.ts +11 -0
  62. package/dist/components/dso-action-list.js +36 -0
  63. package/dist/components/dso-annotation-output.js +1 -1
  64. package/dist/components/dso-card-container.js +1 -1
  65. package/dist/components/dso-date-picker.js +2 -2
  66. package/dist/components/dso-expandable-heading.js +9 -4
  67. package/dist/components/dso-header.js +18 -2
  68. package/dist/components/dso-label.js +1 -8
  69. package/dist/components/dso-list-button.js +1 -1
  70. package/dist/components/dso-ozon-content.js +1 -1
  71. package/dist/components/expandable.js +1440 -4
  72. package/dist/components/focus-trap.esm.js +133 -50
  73. package/dist/components/has-overflow.js +3 -4
  74. package/dist/components/index.d.ts +2 -0
  75. package/dist/components/index.esm.js +97 -17
  76. package/dist/components/index.js +71 -1
  77. package/dist/components/selectable.js +3 -2
  78. package/dist/components/tooltip.js +13 -11
  79. package/dist/dso-toolkit/dso-toolkit.esm.js +1 -1
  80. package/dist/dso-toolkit/index.esm.js +1 -1
  81. package/dist/dso-toolkit/{p-e4f667b3.entry.js → p-0b6fa7d3.entry.js} +1 -1
  82. package/dist/dso-toolkit/p-36224d6f.entry.js +1 -0
  83. package/dist/dso-toolkit/{p-9b07b034.entry.js → p-398a8e0b.entry.js} +1 -1
  84. package/dist/dso-toolkit/p-3b91c3e9.entry.js +1 -0
  85. package/dist/dso-toolkit/p-452b1234.js +1 -0
  86. package/dist/dso-toolkit/p-5950644a.js +5 -0
  87. package/dist/dso-toolkit/p-5de8b79a.entry.js +1 -0
  88. package/dist/dso-toolkit/p-5e50b616.entry.js +1 -0
  89. package/dist/dso-toolkit/p-69f37ab3.entry.js +1 -0
  90. package/dist/dso-toolkit/p-6a99d7f8.entry.js +1 -0
  91. package/dist/dso-toolkit/p-8a77030b.entry.js +1 -0
  92. package/dist/dso-toolkit/p-91963e3d.js +5 -0
  93. package/dist/dso-toolkit/p-96f44d35.entry.js +1 -0
  94. package/dist/dso-toolkit/p-975c172a.entry.js +1 -0
  95. package/dist/dso-toolkit/{p-092dde2f.entry.js → p-a1616935.entry.js} +1 -1
  96. package/dist/dso-toolkit/{p-ba330644.entry.js → p-bb90ea4c.entry.js} +1 -1
  97. package/dist/dso-toolkit/p-bf750b97.js +1 -0
  98. package/dist/dso-toolkit/{p-aab458c4.entry.js → p-c86a5bcb.entry.js} +1 -1
  99. package/dist/dso-toolkit/{p-f2b76233.entry.js → p-cf9b79df.entry.js} +1 -1
  100. package/dist/dso-toolkit/{p-43f3d736.entry.js → p-d10ec2b3.entry.js} +1 -1
  101. package/dist/dso-toolkit/p-e8a6ccf5.entry.js +1 -0
  102. package/dist/dso-toolkit/p-eaae698e.entry.js +1 -0
  103. package/dist/dso-toolkit/p-fa2f1a1c.entry.js +1 -0
  104. package/dist/dso-toolkit/p-fe7ca25f.entry.js +1 -0
  105. package/dist/esm/dso-accordion-section.entry.js +39 -1404
  106. package/dist/esm/dso-action-list-item.entry.js +23 -0
  107. package/dist/esm/dso-action-list.entry.js +16 -0
  108. package/dist/esm/dso-annotation-output.entry.js +1 -1
  109. package/dist/esm/dso-card-container.entry.js +1 -1
  110. package/dist/esm/dso-date-picker.entry.js +1 -1
  111. package/dist/esm/dso-dropdown-menu.entry.js +18 -3
  112. package/dist/esm/dso-expandable-heading.entry.js +7 -3
  113. package/dist/esm/dso-expandable.entry.js +1434 -3
  114. package/dist/esm/dso-header.entry.js +16 -1
  115. package/dist/esm/dso-helpcenter-panel.entry.js +2 -2
  116. package/dist/esm/dso-image-overlay.entry.js +2 -2
  117. package/dist/esm/dso-info_2.entry.js +3 -2
  118. package/dist/esm/dso-label.entry.js +1 -8
  119. package/dist/esm/dso-list-button.entry.js +3 -3
  120. package/dist/esm/dso-modal.entry.js +2 -2
  121. package/dist/esm/dso-ozon-content.entry.js +2 -2
  122. package/dist/esm/dso-table.entry.js +2 -2
  123. package/dist/esm/dso-toolkit.js +1 -1
  124. package/dist/esm/dso-tooltip.entry.js +14 -12
  125. package/dist/esm/dso-viewer-grid.entry.js +2 -2
  126. package/dist/esm/expandable.interfaces-9b1afbe8.js +5 -0
  127. package/dist/esm/{focus-trap.esm-94794d92.js → focus-trap.esm-2a49a38f.js} +134 -51
  128. package/dist/esm/{has-overflow-c44a8a0a.js → has-overflow-fdc85d8f.js} +3 -4
  129. package/dist/esm/{index.esm-8fc07ad8.js → index.esm-3d6c8190.js} +97 -17
  130. package/dist/esm/index.js +69 -0
  131. package/dist/esm/loader.js +1 -1
  132. package/dist/types/components/accordion/accordion.interfaces.d.ts +1 -1
  133. package/dist/types/components/accordion/components/accordion-section.d.ts +4 -8
  134. package/dist/types/components/action-list/action-list.d.ts +5 -0
  135. package/dist/types/components/action-list/components/action-list-item.d.ts +15 -0
  136. package/dist/types/components/dropdown-menu/dropdown-menu.d.ts +5 -0
  137. package/dist/types/components/expandable/expandable.d.ts +25 -1
  138. package/dist/types/components/expandable/expandable.interfaces.d.ts +10 -0
  139. package/dist/types/components/expandable-heading/expandable-heading.d.ts +2 -1
  140. package/dist/types/components/expandable-heading/expandable-heading.interfaces.d.ts +1 -0
  141. package/dist/types/components/header/header.d.ts +3 -0
  142. package/dist/types/components/label/label.d.ts +0 -1
  143. package/dist/types/components/modal/modal-ref.d.ts +8 -0
  144. package/dist/types/components/modal/modal.controller.d.ts +6 -0
  145. package/dist/types/components/modal/modal.d.ts +1 -2
  146. package/dist/types/components/modal/modal.interfaces.d.ts +12 -0
  147. package/dist/types/components.d.ts +82 -4
  148. package/dist/types/index.d.ts +2 -0
  149. package/package.json +11 -11
  150. package/dist/dso-toolkit/p-0fcdc369.entry.js +0 -1
  151. package/dist/dso-toolkit/p-147ec7bd.entry.js +0 -1
  152. package/dist/dso-toolkit/p-22f9240a.entry.js +0 -1
  153. package/dist/dso-toolkit/p-3635427a.js +0 -5
  154. package/dist/dso-toolkit/p-3b83e9c6.entry.js +0 -1
  155. package/dist/dso-toolkit/p-452c7fbb.entry.js +0 -1
  156. package/dist/dso-toolkit/p-4ae40ddc.entry.js +0 -1
  157. package/dist/dso-toolkit/p-4c8426b7.entry.js +0 -1
  158. package/dist/dso-toolkit/p-57ceabab.js +0 -5
  159. package/dist/dso-toolkit/p-9984079e.entry.js +0 -1
  160. package/dist/dso-toolkit/p-cece17a5.entry.js +0 -1
  161. package/dist/dso-toolkit/p-d3ed00f6.js +0 -1
  162. package/dist/dso-toolkit/p-e3bd7689.entry.js +0 -1
  163. package/dist/dso-toolkit/p-f3f0d6c9.entry.js +0 -1
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const index_esm = require('./index.esm-03a9e0b4.js');
3
+ const index_esm = require('./index.esm-0e935715.js');
4
4
 
5
5
  /*!
6
- * focus-trap 7.1.0
6
+ * focus-trap 7.4.3
7
7
  * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
8
8
  */
9
9
 
@@ -29,6 +29,7 @@ function _objectSpread2(target) {
29
29
  return target;
30
30
  }
31
31
  function _defineProperty(obj, key, value) {
32
+ key = _toPropertyKey(key);
32
33
  if (key in obj) {
33
34
  Object.defineProperty(obj, key, {
34
35
  value: value,
@@ -41,8 +42,21 @@ function _defineProperty(obj, key, value) {
41
42
  }
42
43
  return obj;
43
44
  }
45
+ function _toPrimitive(input, hint) {
46
+ if (typeof input !== "object" || input === null) return input;
47
+ var prim = input[Symbol.toPrimitive];
48
+ if (prim !== undefined) {
49
+ var res = prim.call(input, hint || "default");
50
+ if (typeof res !== "object") return res;
51
+ throw new TypeError("@@toPrimitive must return a primitive value.");
52
+ }
53
+ return (hint === "string" ? String : Number)(input);
54
+ }
55
+ function _toPropertyKey(arg) {
56
+ var key = _toPrimitive(arg, "string");
57
+ return typeof key === "symbol" ? key : String(key);
58
+ }
44
59
 
45
- var rooTrapStack = [];
46
60
  var activeFocusTraps = {
47
61
  activateTrap: function activateTrap(trapStack, trap) {
48
62
  if (trapStack.length > 0) {
@@ -79,6 +93,16 @@ var isEscapeEvent = function isEscapeEvent(e) {
79
93
  var isTabEvent = function isTabEvent(e) {
80
94
  return e.key === 'Tab' || e.keyCode === 9;
81
95
  };
96
+
97
+ // checks for TAB by default
98
+ var isKeyForward = function isKeyForward(e) {
99
+ return isTabEvent(e) && !e.shiftKey;
100
+ };
101
+
102
+ // checks for SHIFT+TAB by default
103
+ var isKeyBackward = function isKeyBackward(e) {
104
+ return isTabEvent(e) && e.shiftKey;
105
+ };
82
106
  var delay = function delay(fn) {
83
107
  return setTimeout(fn, 0);
84
108
  };
@@ -122,15 +146,21 @@ var getActualTarget = function getActualTarget(event) {
122
146
  // composedPath()[0] === event.target always).
123
147
  return event.target.shadowRoot && typeof event.composedPath === 'function' ? event.composedPath()[0] : event.target;
124
148
  };
149
+
150
+ // NOTE: this must be _outside_ `createFocusTrap()` to make sure all traps in this
151
+ // current instance use the same stack if `userOptions.trapStack` isn't specified
152
+ var internalTrapStack = [];
125
153
  var createFocusTrap = function createFocusTrap(elements, userOptions) {
126
154
  // SSR: a live trap shouldn't be created in this type of environment so this
127
155
  // should be safe code to execute if the `document` option isn't specified
128
156
  var doc = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.document) || document;
129
- var trapStack = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.trapStack) || rooTrapStack;
157
+ var trapStack = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.trapStack) || internalTrapStack;
130
158
  var config = _objectSpread2({
131
159
  returnFocusOnDeactivate: true,
132
160
  escapeDeactivates: true,
133
- delayInitialFocus: true
161
+ delayInitialFocus: true,
162
+ isKeyForward: isKeyForward,
163
+ isKeyBackward: isKeyBackward
134
164
  }, userOptions);
135
165
  var state = {
136
166
  // containers given to createFocusTrap()
@@ -182,23 +212,24 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
182
212
  /**
183
213
  * Finds the index of the container that contains the element.
184
214
  * @param {HTMLElement} element
215
+ * @param {Event} [event]
185
216
  * @returns {number} Index of the container in either `state.containers` or
186
217
  * `state.containerGroups` (the order/length of these lists are the same); -1
187
218
  * if the element isn't found.
188
219
  */
189
- var findContainerIndex = function findContainerIndex(element) {
220
+ var findContainerIndex = function findContainerIndex(element, event) {
221
+ var composedPath = typeof (event === null || event === void 0 ? void 0 : event.composedPath) === 'function' ? event.composedPath() : undefined;
190
222
  // NOTE: search `containerGroups` because it's possible a group contains no tabbable
191
223
  // nodes, but still contains focusable nodes (e.g. if they all have `tabindex=-1`)
192
224
  // and we still need to find the element in there
193
225
  return state.containerGroups.findIndex(function (_ref) {
194
226
  var container = _ref.container,
195
227
  tabbableNodes = _ref.tabbableNodes;
196
- return container.contains(element) ||
197
- // fall back to explicit tabbable search which will take into consideration any
228
+ return container.contains(element) || ( // fall back to explicit tabbable search which will take into consideration any
198
229
  // web components if the `tabbableOptions.getShadowRoot` option was used for
199
230
  // the trap, enabling shadow DOM support in tabbable (`Node.contains()` doesn't
200
231
  // look inside web components even if open)
201
- tabbableNodes.find(function (node) {
232
+ composedPath === null || composedPath === void 0 ? void 0 : composedPath.includes(container)) || tabbableNodes.find(function (node) {
202
233
  return node === element;
203
234
  });
204
235
  });
@@ -254,8 +285,8 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
254
285
  if (node === false) {
255
286
  return false;
256
287
  }
257
- if (node === undefined) {
258
- // option not specified: use fallback options
288
+ if (node === undefined || !index_esm.isFocusable(node, config.tabbableOptions)) {
289
+ // option not specified nor focusable: use fallback options
259
290
  if (findContainerIndex(doc.activeElement) >= 0) {
260
291
  node = doc.activeElement;
261
292
  } else {
@@ -359,25 +390,20 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
359
390
  // so that it precedes the focus event.
360
391
  var checkPointerDown = function checkPointerDown(e) {
361
392
  var target = getActualTarget(e);
362
- if (findContainerIndex(target) >= 0) {
393
+ if (findContainerIndex(target, e) >= 0) {
363
394
  // allow the click since it ocurred inside the trap
364
395
  return;
365
396
  }
366
397
  if (valueOrHandler(config.clickOutsideDeactivates, e)) {
367
398
  // immediately deactivate the trap
368
399
  trap.deactivate({
369
- // if, on deactivation, we should return focus to the node originally-focused
370
- // when the trap was activated (or the configured `setReturnFocus` node),
371
- // then assume it's also OK to return focus to the outside node that was
372
- // just clicked, causing deactivation, as long as that node is focusable;
373
- // if it isn't focusable, then return focus to the original node focused
374
- // on activation (or the configured `setReturnFocus` node)
375
400
  // NOTE: by setting `returnFocus: false`, deactivate() will do nothing,
376
401
  // which will result in the outside click setting focus to the node
377
- // that was clicked, whether it's focusable or not; by setting
402
+ // that was clicked (and if not focusable, to "nothing"); by setting
378
403
  // `returnFocus: true`, we'll attempt to re-focus the node originally-focused
379
- // on activation (or the configured `setReturnFocus` node)
380
- returnFocus: config.returnFocusOnDeactivate && !index_esm.isFocusable(target, config.tabbableOptions)
404
+ // on activation (or the configured `setReturnFocus` node), whether the
405
+ // outside click was on a focusable node or not
406
+ returnFocus: config.returnFocusOnDeactivate
381
407
  });
382
408
  return;
383
409
  }
@@ -397,7 +423,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
397
423
  // In case focus escapes the trap for some strange reason, pull it back in.
398
424
  var checkFocusIn = function checkFocusIn(e) {
399
425
  var target = getActualTarget(e);
400
- var targetContained = findContainerIndex(target) >= 0;
426
+ var targetContained = findContainerIndex(target, e) >= 0;
401
427
 
402
428
  // In Firefox when you Tab out of an iframe the Document is briefly focused.
403
429
  if (targetContained || target instanceof Document) {
@@ -411,31 +437,32 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
411
437
  }
412
438
  };
413
439
 
414
- // Hijack Tab events on the first and last focusable nodes of the trap,
440
+ // Hijack key nav events on the first and last focusable nodes of the trap,
415
441
  // in order to prevent focus from escaping. If it escapes for even a
416
442
  // moment it can end up scrolling the page and causing confusion so we
417
443
  // kind of need to capture the action at the keydown phase.
418
- var checkTab = function checkTab(e) {
419
- var target = getActualTarget(e);
444
+ var checkKeyNav = function checkKeyNav(event) {
445
+ var isBackward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
446
+ var target = getActualTarget(event);
420
447
  updateTabbableNodes();
421
448
  var destinationNode = null;
422
449
  if (state.tabbableGroups.length > 0) {
423
450
  // make sure the target is actually contained in a group
424
451
  // NOTE: the target may also be the container itself if it's focusable
425
452
  // with tabIndex='-1' and was given initial focus
426
- var containerIndex = findContainerIndex(target);
453
+ var containerIndex = findContainerIndex(target, event);
427
454
  var containerGroup = containerIndex >= 0 ? state.containerGroups[containerIndex] : undefined;
428
455
  if (containerIndex < 0) {
429
456
  // target not found in any group: quite possible focus has escaped the trap,
430
- // so bring it back in to...
431
- if (e.shiftKey) {
457
+ // so bring it back into...
458
+ if (isBackward) {
432
459
  // ...the last node in the last group
433
460
  destinationNode = state.tabbableGroups[state.tabbableGroups.length - 1].lastTabbableNode;
434
461
  } else {
435
462
  // ...the first node in the first group
436
463
  destinationNode = state.tabbableGroups[0].firstTabbableNode;
437
464
  }
438
- } else if (e.shiftKey) {
465
+ } else if (isBackward) {
439
466
  // REVERSE
440
467
 
441
468
  // is the target the first tabbable node in a group?
@@ -459,6 +486,10 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
459
486
  var destinationGroupIndex = startOfGroupIndex === 0 ? state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
460
487
  var destinationGroup = state.tabbableGroups[destinationGroupIndex];
461
488
  destinationNode = destinationGroup.lastTabbableNode;
489
+ } else if (!isTabEvent(event)) {
490
+ // user must have customized the nav keys so we have to move focus manually _within_
491
+ // the active group: do this based on the order determined by tabbable()
492
+ destinationNode = containerGroup.nextTabbableNode(target, false);
462
493
  }
463
494
  } else {
464
495
  // FORWARD
@@ -484,33 +515,43 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
484
515
  var _destinationGroupIndex = lastOfGroupIndex === state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
485
516
  var _destinationGroup = state.tabbableGroups[_destinationGroupIndex];
486
517
  destinationNode = _destinationGroup.firstTabbableNode;
518
+ } else if (!isTabEvent(event)) {
519
+ // user must have customized the nav keys so we have to move focus manually _within_
520
+ // the active group: do this based on the order determined by tabbable()
521
+ destinationNode = containerGroup.nextTabbableNode(target);
487
522
  }
488
523
  }
489
524
  } else {
525
+ // no groups available
490
526
  // NOTE: the fallbackFocus option does not support returning false to opt-out
491
527
  destinationNode = getNodeForOption('fallbackFocus');
492
528
  }
493
529
  if (destinationNode) {
494
- e.preventDefault();
530
+ if (isTabEvent(event)) {
531
+ // since tab natively moves focus, we wouldn't have a destination node unless we
532
+ // were on the edge of a container and had to move to the next/previous edge, in
533
+ // which case we want to prevent default to keep the browser from moving focus
534
+ // to where it normally would
535
+ event.preventDefault();
536
+ }
495
537
  tryFocus(destinationNode);
496
538
  }
497
539
  // else, let the browser take care of [shift+]tab and move the focus
498
540
  };
499
541
 
500
- var checkKey = function checkKey(e) {
501
- if (isEscapeEvent(e) && valueOrHandler(config.escapeDeactivates, e) !== false) {
502
- e.preventDefault();
542
+ var checkKey = function checkKey(event) {
543
+ if (isEscapeEvent(event) && valueOrHandler(config.escapeDeactivates, event) !== false) {
544
+ event.preventDefault();
503
545
  trap.deactivate();
504
546
  return;
505
547
  }
506
- if (isTabEvent(e)) {
507
- checkTab(e);
508
- return;
548
+ if (config.isKeyForward(event) || config.isKeyBackward(event)) {
549
+ checkKeyNav(event, config.isKeyBackward(event));
509
550
  }
510
551
  };
511
552
  var checkClick = function checkClick(e) {
512
553
  var target = getActualTarget(e);
513
- if (findContainerIndex(target) >= 0) {
554
+ if (findContainerIndex(target, e) >= 0) {
514
555
  return;
515
556
  }
516
557
  if (valueOrHandler(config.clickOutsideDeactivates, e)) {
@@ -571,6 +612,43 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
571
612
  return trap;
572
613
  };
573
614
 
615
+ //
616
+ // MUTATION OBSERVER
617
+ //
618
+
619
+ var checkDomRemoval = function checkDomRemoval(mutations) {
620
+ var isFocusedNodeRemoved = mutations.some(function (mutation) {
621
+ var removedNodes = Array.from(mutation.removedNodes);
622
+ return removedNodes.some(function (node) {
623
+ return node === state.mostRecentlyFocusedNode;
624
+ });
625
+ });
626
+
627
+ // If the currently focused is removed then browsers will move focus to the
628
+ // <body> element. If this happens, try to move focus back into the trap.
629
+ if (isFocusedNodeRemoved) {
630
+ tryFocus(getInitialFocusNode());
631
+ }
632
+ };
633
+
634
+ // Use MutationObserver - if supported - to detect if focused node is removed
635
+ // from the DOM.
636
+ var mutationObserver = typeof window !== 'undefined' && 'MutationObserver' in window ? new MutationObserver(checkDomRemoval) : undefined;
637
+ var updateObservedNodes = function updateObservedNodes() {
638
+ if (!mutationObserver) {
639
+ return;
640
+ }
641
+ mutationObserver.disconnect();
642
+ if (state.active && !state.paused) {
643
+ state.containers.map(function (container) {
644
+ mutationObserver.observe(container, {
645
+ subtree: true,
646
+ childList: true
647
+ });
648
+ });
649
+ }
650
+ };
651
+
574
652
  //
575
653
  // TRAP DEFINITION
576
654
  //
@@ -595,17 +673,14 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
595
673
  state.active = true;
596
674
  state.paused = false;
597
675
  state.nodeFocusedBeforeActivation = doc.activeElement;
598
- if (onActivate) {
599
- onActivate();
600
- }
676
+ onActivate === null || onActivate === void 0 ? void 0 : onActivate();
601
677
  var finishActivation = function finishActivation() {
602
678
  if (checkCanFocusTrap) {
603
679
  updateTabbableNodes();
604
680
  }
605
681
  addListeners();
606
- if (onPostActivate) {
607
- onPostActivate();
608
- }
682
+ updateObservedNodes();
683
+ onPostActivate === null || onPostActivate === void 0 ? void 0 : onPostActivate();
609
684
  };
610
685
  if (checkCanFocusTrap) {
611
686
  checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
@@ -628,22 +703,19 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
628
703
  removeListeners();
629
704
  state.active = false;
630
705
  state.paused = false;
706
+ updateObservedNodes();
631
707
  activeFocusTraps.deactivateTrap(trapStack, trap);
632
708
  var onDeactivate = getOption(options, 'onDeactivate');
633
709
  var onPostDeactivate = getOption(options, 'onPostDeactivate');
634
710
  var checkCanReturnFocus = getOption(options, 'checkCanReturnFocus');
635
711
  var returnFocus = getOption(options, 'returnFocus', 'returnFocusOnDeactivate');
636
- if (onDeactivate) {
637
- onDeactivate();
638
- }
712
+ onDeactivate === null || onDeactivate === void 0 ? void 0 : onDeactivate();
639
713
  var finishDeactivation = function finishDeactivation() {
640
714
  delay(function () {
641
715
  if (returnFocus) {
642
716
  tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
643
717
  }
644
- if (onPostDeactivate) {
645
- onPostDeactivate();
646
- }
718
+ onPostDeactivate === null || onPostDeactivate === void 0 ? void 0 : onPostDeactivate();
647
719
  });
648
720
  };
649
721
  if (returnFocus && checkCanReturnFocus) {
@@ -653,21 +725,31 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
653
725
  finishDeactivation();
654
726
  return this;
655
727
  },
656
- pause: function pause() {
728
+ pause: function pause(pauseOptions) {
657
729
  if (state.paused || !state.active) {
658
730
  return this;
659
731
  }
732
+ var onPause = getOption(pauseOptions, 'onPause');
733
+ var onPostPause = getOption(pauseOptions, 'onPostPause');
660
734
  state.paused = true;
735
+ onPause === null || onPause === void 0 ? void 0 : onPause();
661
736
  removeListeners();
737
+ updateObservedNodes();
738
+ onPostPause === null || onPostPause === void 0 ? void 0 : onPostPause();
662
739
  return this;
663
740
  },
664
- unpause: function unpause() {
741
+ unpause: function unpause(unpauseOptions) {
665
742
  if (!state.paused || !state.active) {
666
743
  return this;
667
744
  }
745
+ var onUnpause = getOption(unpauseOptions, 'onUnpause');
746
+ var onPostUnpause = getOption(unpauseOptions, 'onPostUnpause');
668
747
  state.paused = false;
748
+ onUnpause === null || onUnpause === void 0 ? void 0 : onUnpause();
669
749
  updateTabbableNodes();
670
750
  addListeners();
751
+ updateObservedNodes();
752
+ onPostUnpause === null || onPostUnpause === void 0 ? void 0 : onPostUnpause();
671
753
  return this;
672
754
  },
673
755
  updateContainerElements: function updateContainerElements(containerElements) {
@@ -678,6 +760,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
678
760
  if (state.active) {
679
761
  updateTabbableNodes();
680
762
  }
763
+ updateObservedNodes();
681
764
  return this;
682
765
  }
683
766
  };
@@ -163,7 +163,7 @@ var round = Math.round;
163
163
  function getUAString() {
164
164
  var uaData = navigator.userAgentData;
165
165
 
166
- if (uaData != null && uaData.brands) {
166
+ if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {
167
167
  return uaData.brands.map(function (item) {
168
168
  return item.brand + "/" + item.version;
169
169
  }).join(' ');
@@ -482,10 +482,9 @@ var unsetSides = {
482
482
  // Zooming can change the DPR, but it seems to report a value that will
483
483
  // cleanly divide the values into the appropriate subpixels.
484
484
 
485
- function roundOffsetsByDPR(_ref) {
485
+ function roundOffsetsByDPR(_ref, win) {
486
486
  var x = _ref.x,
487
487
  y = _ref.y;
488
- var win = window;
489
488
  var dpr = win.devicePixelRatio || 1;
490
489
  return {
491
490
  x: round(x * dpr) / dpr || 0,
@@ -568,7 +567,7 @@ function mapToStyles(_ref2) {
568
567
  var _ref4 = roundOffsets === true ? roundOffsetsByDPR({
569
568
  x: x,
570
569
  y: y
571
- }) : {
570
+ }, getWindow(popper)) : {
572
571
  x: x,
573
572
  y: y
574
573
  };
@@ -2,8 +2,75 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ const expandable_interfaces = require('./expandable.interfaces-19b608b9.js');
5
6
  const mapControls_interfaces = require('./map-controls.interfaces-5ceec716.js');
6
7
 
8
+ class DsoModalRef {
9
+ constructor(modalElement) {
10
+ this.modalElement = modalElement;
11
+ if (!modalElement) {
12
+ throw new Error("unable to add event listener. try opening the modal first");
13
+ }
14
+ }
15
+ /** Removes the modal from the DOM. */
16
+ close() {
17
+ document.body.removeChild(this.modalElement);
18
+ }
19
+ addEventListener(eventName, fn) {
20
+ this.modalElement.addEventListener(eventName, fn);
21
+ }
22
+ removeEventListener(eventName, fn) {
23
+ this.modalElement.removeEventListener(eventName, fn);
24
+ }
25
+ }
7
26
 
27
+ class DsoModalController {
28
+ open(modal, options) {
29
+ const dsoModalElement = this.createModal(modal, options);
30
+ document.body.appendChild(dsoModalElement);
31
+ return new DsoModalRef(dsoModalElement);
32
+ }
33
+ createModal({ title, body, footer }, options) {
34
+ const element = document.createElement(`dso-modal`);
35
+ if (title) {
36
+ element.setAttribute("modal-title", title);
37
+ }
38
+ if (options) {
39
+ const { role, showCloseButton, initialFocus } = options;
40
+ if (role) {
41
+ element.role = role;
42
+ }
43
+ if (showCloseButton) {
44
+ element.setAttribute("show-close-button", showCloseButton ? "true" : "false");
45
+ }
46
+ if (initialFocus) {
47
+ element.setAttribute("initial-focus", initialFocus);
48
+ }
49
+ }
50
+ const bodyDiv = document.createElement("div");
51
+ bodyDiv.setAttribute("slot", "body");
52
+ if (typeof body === "string") {
53
+ bodyDiv.innerHTML = body;
54
+ }
55
+ else {
56
+ bodyDiv.appendChild(body);
57
+ }
58
+ element.appendChild(bodyDiv);
59
+ if (footer) {
60
+ const footerDiv = document.createElement("div");
61
+ footerDiv.setAttribute("slot", "footer");
62
+ if (typeof footer === "string") {
63
+ footerDiv.innerHTML = footer;
64
+ }
65
+ else {
66
+ footerDiv.appendChild(footer);
67
+ }
68
+ element.appendChild(footerDiv);
69
+ }
70
+ return element;
71
+ }
72
+ }
8
73
 
74
+ exports.isExpandable = expandable_interfaces.isExpandable;
9
75
  exports.transitionDuration = mapControls_interfaces.transitionDuration;
76
+ exports.DsoModalController = DsoModalController;