coveragebook_components 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/build/coco/app.css +427 -303
  3. data/app/assets/build/coco/app.js +458 -226
  4. data/app/assets/build/coco/book.js +378 -175
  5. data/app/assets/build/coco/icons/armchair.svg +1 -1
  6. data/app/assets/build/coco/icons/folder-archive.svg +1 -1
  7. data/app/assets/build/coco/icons/folder-check.svg +1 -1
  8. data/app/assets/build/coco/icons/folder-clock.svg +1 -1
  9. data/app/assets/build/coco/icons/folder-closed.svg +1 -1
  10. data/app/assets/build/coco/icons/folder-cog.svg +1 -1
  11. data/app/assets/build/coco/icons/folder-down.svg +1 -1
  12. data/app/assets/build/coco/icons/folder-edit.svg +1 -1
  13. data/app/assets/build/coco/icons/folder-git.svg +1 -1
  14. data/app/assets/build/coco/icons/folder-heart.svg +1 -1
  15. data/app/assets/build/coco/icons/folder-input.svg +1 -1
  16. data/app/assets/build/coco/icons/folder-key.svg +1 -1
  17. data/app/assets/build/coco/icons/folder-lock.svg +1 -1
  18. data/app/assets/build/coco/icons/folder-minus.svg +1 -1
  19. data/app/assets/build/coco/icons/folder-open.svg +1 -1
  20. data/app/assets/build/coco/icons/folder-plus.svg +1 -1
  21. data/app/assets/build/coco/icons/folder-search-2.svg +1 -1
  22. data/app/assets/build/coco/icons/folder-search.svg +1 -1
  23. data/app/assets/build/coco/icons/folder-tree.svg +1 -1
  24. data/app/assets/build/coco/icons/folder-up.svg +1 -1
  25. data/app/assets/build/coco/icons/folder-x.svg +1 -1
  26. data/app/assets/build/coco/icons/folder.svg +1 -1
  27. data/app/assets/build/coco/icons/folders.svg +1 -1
  28. data/app/assets/build/coco/icons/git-commit-vertical.svg +1 -0
  29. data/app/assets/build/coco/icons/git-compare-arrows.svg +1 -0
  30. data/app/assets/build/coco/icons/git-fork.svg +1 -1
  31. data/app/assets/build/coco/icons/git-graph.svg +1 -0
  32. data/app/assets/build/coco/icons/git-pull-request-arrow.svg +1 -0
  33. data/app/assets/build/coco/icons/git-pull-request-closed.svg +1 -1
  34. data/app/assets/build/coco/icons/git-pull-request-create-arrow.svg +1 -0
  35. data/app/assets/build/coco/icons/git-pull-request-create.svg +1 -0
  36. data/app/assets/build/coco/icons/power-circle.svg +1 -0
  37. data/app/assets/build/coco/icons/power-square.svg +1 -0
  38. data/app/assets/build/coco/icons/power.svg +1 -1
  39. data/app/components/coco/app/blocks/sidebar_nav/item/item.css +121 -0
  40. data/app/components/coco/app/blocks/sidebar_nav/item/item.html.erb +9 -0
  41. data/app/components/coco/app/blocks/{sidebar_nav_item/sidebar_nav_item.js → sidebar_nav/item/item.js} +12 -5
  42. data/app/components/coco/app/blocks/sidebar_nav/item/item.rb +50 -0
  43. data/app/components/coco/app/blocks/sidebar_nav/menu/menu.css +138 -0
  44. data/app/components/coco/app/blocks/sidebar_nav/menu/menu.html.erb +24 -0
  45. data/app/components/coco/app/blocks/sidebar_nav/menu/menu.js +13 -0
  46. data/app/components/coco/app/blocks/sidebar_nav/menu/menu.rb +48 -0
  47. data/app/components/coco/app/blocks/sidebar_nav/navbar/navbar.css +75 -0
  48. data/app/components/coco/app/blocks/sidebar_nav/navbar/navbar.html.erb +29 -0
  49. data/app/components/coco/app/blocks/sidebar_nav/navbar/navbar.rb +50 -0
  50. data/app/components/coco/base/icon/icon.rb +1 -0
  51. data/app/components/coco/component.rb +2 -2
  52. data/app/helpers/coco/app_helper.rb +5 -1
  53. data/app/helpers/coco/book_helper.rb +4 -4
  54. data/app/helpers/coco/component_helper.rb +2 -2
  55. data/app/helpers/coco/integration_helper.rb +4 -4
  56. data/config/icons.json +9 -1
  57. data/config/tokens.cjs +6 -0
  58. data/lib/coco/options/group.rb +9 -9
  59. data/lib/coco/test_helpers.rb +2 -2
  60. data/lib/coco.rb +1 -1
  61. metadata +23 -11
  62. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.css +0 -110
  63. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.html.erb +0 -42
  64. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.rb +0 -28
  65. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.css +0 -153
  66. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.html.erb +0 -45
  67. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.rb +0 -108
  68. /data/app/assets/build/coco/icons/{git-commit.svg → git-commit-horizontal.svg} +0 -0
  69. /data/app/components/coco/app/blocks/sidebar_nav/{sidebar_nav.js → navbar/navbar.js} +0 -0
@@ -10443,7 +10443,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10443
10443
  let evaluate2 = evaluateLater2(expression);
10444
10444
  let options = {
10445
10445
  rootMargin: getRootMargin(modifiers),
10446
- threshold: getThreshhold(modifiers)
10446
+ threshold: getThreshold(modifiers)
10447
10447
  };
10448
10448
  let observer2 = new IntersectionObserver((entries) => {
10449
10449
  entries.forEach((entry) => {
@@ -10459,7 +10459,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10459
10459
  });
10460
10460
  });
10461
10461
  }
10462
- function getThreshhold(modifiers) {
10462
+ function getThreshold(modifiers) {
10463
10463
  if (modifiers.includes("full"))
10464
10464
  return 0.99;
10465
10465
  if (modifiers.includes("half"))
@@ -10507,8 +10507,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10507
10507
  evaluator((value2) => {
10508
10508
  result = typeof value2 === "function" ? value2(input) : value2;
10509
10509
  }, { scope: {
10510
- $input: input,
10511
- $money: formatMoney.bind({ el })
10510
+ // These are "magics" we'll make available to the x-mask:function:
10511
+ "$input": input,
10512
+ "$money": formatMoney.bind({ el })
10512
10513
  } });
10513
10514
  });
10514
10515
  return result;
@@ -10556,7 +10557,13 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10556
10557
  let unformattedValue = el.value;
10557
10558
  callback();
10558
10559
  let beforeLeftOfCursorBeforeFormatting = unformattedValue.slice(0, cursorPosition);
10559
- let newPosition = buildUp(template, stripDown(template, beforeLeftOfCursorBeforeFormatting)).length;
10560
+ let newPosition = buildUp(
10561
+ template,
10562
+ stripDown(
10563
+ template,
10564
+ beforeLeftOfCursorBeforeFormatting
10565
+ )
10566
+ ).length;
10560
10567
  el.setSelectionRange(newPosition, newPosition);
10561
10568
  }
10562
10569
  function stripDown(template, input) {
@@ -10564,7 +10571,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10564
10571
  let output = "";
10565
10572
  let regexes = {
10566
10573
  "9": /[0-9]/,
10567
- a: /[a-zA-Z]/,
10574
+ "a": /[a-zA-Z]/,
10568
10575
  "*": /[a-zA-Z0-9]/
10569
10576
  };
10570
10577
  let wildcardTemplate = "";
@@ -10614,7 +10621,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10614
10621
  return "-";
10615
10622
  if (/^\D+$/.test(input))
10616
10623
  return "9";
10617
- thousands = thousands != null ? thousands : delimiter === "," ? "." : ",";
10624
+ if (thousands === null || thousands === void 0) {
10625
+ thousands = delimiter === "," ? "." : ",";
10626
+ }
10618
10627
  let addThousands = (input2, thousands2) => {
10619
10628
  let output = "";
10620
10629
  let counter = 0;
@@ -10649,10 +10658,16 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10649
10658
  var module_default5 = src_default5;
10650
10659
 
10651
10660
  // ../../../node_modules/@alpinejs/focus/dist/module.esm.js
10652
- var candidateSelectors = ["input", "select", "textarea", "a[href]", "button", "[tabindex]", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])', "details>summary:first-of-type", "details"];
10661
+ var candidateSelectors = ["input", "select", "textarea", "a[href]", "button", "[tabindex]:not(slot)", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])', "details>summary:first-of-type", "details"];
10653
10662
  var candidateSelector = /* @__PURE__ */ candidateSelectors.join(",");
10654
- var matches = typeof Element === "undefined" ? function() {
10663
+ var NoElement = typeof Element === "undefined";
10664
+ var matches = NoElement ? function() {
10655
10665
  } : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
10666
+ var getRootNode = !NoElement && Element.prototype.getRootNode ? function(element) {
10667
+ return element.getRootNode();
10668
+ } : function(element) {
10669
+ return element.ownerDocument;
10670
+ };
10656
10671
  var getCandidates = function getCandidates2(el, includeContainer, filter) {
10657
10672
  var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
10658
10673
  if (includeContainer && matches.call(el, candidateSelector)) {
@@ -10661,19 +10676,53 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10661
10676
  candidates = candidates.filter(filter);
10662
10677
  return candidates;
10663
10678
  };
10664
- var isContentEditable = function isContentEditable2(node) {
10665
- return node.contentEditable === "true";
10666
- };
10667
- var getTabindex = function getTabindex2(node) {
10668
- var tabindexAttr = parseInt(node.getAttribute("tabindex"), 10);
10669
- if (!isNaN(tabindexAttr)) {
10670
- return tabindexAttr;
10671
- }
10672
- if (isContentEditable(node)) {
10673
- return 0;
10679
+ var getCandidatesIteratively = function getCandidatesIteratively2(elements, includeContainer, options) {
10680
+ var candidates = [];
10681
+ var elementsToCheck = Array.from(elements);
10682
+ while (elementsToCheck.length) {
10683
+ var element = elementsToCheck.shift();
10684
+ if (element.tagName === "SLOT") {
10685
+ var assigned = element.assignedElements();
10686
+ var content2 = assigned.length ? assigned : element.children;
10687
+ var nestedCandidates = getCandidatesIteratively2(content2, true, options);
10688
+ if (options.flatten) {
10689
+ candidates.push.apply(candidates, nestedCandidates);
10690
+ } else {
10691
+ candidates.push({
10692
+ scope: element,
10693
+ candidates: nestedCandidates
10694
+ });
10695
+ }
10696
+ } else {
10697
+ var validCandidate = matches.call(element, candidateSelector);
10698
+ if (validCandidate && options.filter(element) && (includeContainer || !elements.includes(element))) {
10699
+ candidates.push(element);
10700
+ }
10701
+ var shadowRoot = element.shadowRoot || // check for an undisclosed shadow
10702
+ typeof options.getShadowRoot === "function" && options.getShadowRoot(element);
10703
+ var validShadowRoot = !options.shadowRootFilter || options.shadowRootFilter(element);
10704
+ if (shadowRoot && validShadowRoot) {
10705
+ var _nestedCandidates = getCandidatesIteratively2(shadowRoot === true ? element.children : shadowRoot.children, true, options);
10706
+ if (options.flatten) {
10707
+ candidates.push.apply(candidates, _nestedCandidates);
10708
+ } else {
10709
+ candidates.push({
10710
+ scope: element,
10711
+ candidates: _nestedCandidates
10712
+ });
10713
+ }
10714
+ } else {
10715
+ elementsToCheck.unshift.apply(elementsToCheck, element.children);
10716
+ }
10717
+ }
10674
10718
  }
10675
- if ((node.nodeName === "AUDIO" || node.nodeName === "VIDEO" || node.nodeName === "DETAILS") && node.getAttribute("tabindex") === null) {
10676
- return 0;
10719
+ return candidates;
10720
+ };
10721
+ var getTabindex = function getTabindex2(node, isScope) {
10722
+ if (node.tabIndex < 0) {
10723
+ if ((isScope || /^(AUDIO|VIDEO|DETAILS)$/.test(node.tagName) || node.isContentEditable) && isNaN(parseInt(node.getAttribute("tabindex"), 10))) {
10724
+ return 0;
10725
+ }
10677
10726
  }
10678
10727
  return node.tabIndex;
10679
10728
  };
@@ -10703,7 +10752,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10703
10752
  if (!node.name) {
10704
10753
  return true;
10705
10754
  }
10706
- var radioScope = node.form || node.ownerDocument;
10755
+ var radioScope = node.form || getRootNode(node);
10707
10756
  var queryRadios = function queryRadios2(name) {
10708
10757
  return radioScope.querySelectorAll('input[type="radio"][name="' + name + '"]');
10709
10758
  };
@@ -10727,7 +10776,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10727
10776
  var isNonTabbableRadio = function isNonTabbableRadio2(node) {
10728
10777
  return isRadio(node) && !isTabbableRadio(node);
10729
10778
  };
10730
- var isHidden = function isHidden2(node, displayCheck) {
10779
+ var isZeroArea = function isZeroArea2(node) {
10780
+ var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height;
10781
+ return width === 0 && height === 0;
10782
+ };
10783
+ var isHidden = function isHidden2(node, _ref) {
10784
+ var displayCheck = _ref.displayCheck, getShadowRoot = _ref.getShadowRoot;
10731
10785
  if (getComputedStyle(node).visibility === "hidden") {
10732
10786
  return true;
10733
10787
  }
@@ -10736,31 +10790,43 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10736
10790
  if (matches.call(nodeUnderDetails, "details:not([open]) *")) {
10737
10791
  return true;
10738
10792
  }
10793
+ var nodeRootHost = getRootNode(node).host;
10794
+ var nodeIsAttached = (nodeRootHost === null || nodeRootHost === void 0 ? void 0 : nodeRootHost.ownerDocument.contains(nodeRootHost)) || node.ownerDocument.contains(node);
10739
10795
  if (!displayCheck || displayCheck === "full") {
10740
- while (node) {
10741
- if (getComputedStyle(node).display === "none") {
10742
- return true;
10796
+ if (typeof getShadowRoot === "function") {
10797
+ var originalNode = node;
10798
+ while (node) {
10799
+ var parentElement = node.parentElement;
10800
+ var rootNode = getRootNode(node);
10801
+ if (parentElement && !parentElement.shadowRoot && getShadowRoot(parentElement) === true) {
10802
+ return isZeroArea(node);
10803
+ } else if (node.assignedSlot) {
10804
+ node = node.assignedSlot;
10805
+ } else if (!parentElement && rootNode !== node.ownerDocument) {
10806
+ node = rootNode.host;
10807
+ } else {
10808
+ node = parentElement;
10809
+ }
10743
10810
  }
10744
- node = node.parentElement;
10811
+ node = originalNode;
10812
+ }
10813
+ if (nodeIsAttached) {
10814
+ return !node.getClientRects().length;
10745
10815
  }
10746
10816
  } else if (displayCheck === "non-zero-area") {
10747
- var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height;
10748
- return width === 0 && height === 0;
10817
+ return isZeroArea(node);
10749
10818
  }
10750
10819
  return false;
10751
10820
  };
10752
10821
  var isDisabledFromFieldset = function isDisabledFromFieldset2(node) {
10753
- if (isInput(node) || node.tagName === "SELECT" || node.tagName === "TEXTAREA" || node.tagName === "BUTTON") {
10822
+ if (/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(node.tagName)) {
10754
10823
  var parentNode = node.parentElement;
10755
10824
  while (parentNode) {
10756
10825
  if (parentNode.tagName === "FIELDSET" && parentNode.disabled) {
10757
10826
  for (var i2 = 0; i2 < parentNode.children.length; i2++) {
10758
10827
  var child = parentNode.children.item(i2);
10759
10828
  if (child.tagName === "LEGEND") {
10760
- if (child.contains(node)) {
10761
- return false;
10762
- }
10763
- return true;
10829
+ return matches.call(parentNode, "fieldset[disabled] *") ? true : !child.contains(node);
10764
10830
  }
10765
10831
  }
10766
10832
  return true;
@@ -10771,44 +10837,89 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10771
10837
  return false;
10772
10838
  };
10773
10839
  var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable2(options, node) {
10774
- if (node.disabled || isHiddenInput(node) || isHidden(node, options.displayCheck) || isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
10840
+ if (node.disabled || isHiddenInput(node) || isHidden(node, options) || // For a details element with a summary, the summary element gets the focus
10841
+ isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
10775
10842
  return false;
10776
10843
  }
10777
10844
  return true;
10778
10845
  };
10779
10846
  var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable2(options, node) {
10780
- if (!isNodeMatchingSelectorFocusable(options, node) || isNonTabbableRadio(node) || getTabindex(node) < 0) {
10847
+ if (isNonTabbableRadio(node) || getTabindex(node) < 0 || !isNodeMatchingSelectorFocusable(options, node)) {
10781
10848
  return false;
10782
10849
  }
10783
10850
  return true;
10784
10851
  };
10785
- var tabbable = function tabbable2(el, options) {
10786
- options = options || {};
10852
+ var isValidShadowRootTabbable = function isValidShadowRootTabbable2(shadowHostNode) {
10853
+ var tabIndex = parseInt(shadowHostNode.getAttribute("tabindex"), 10);
10854
+ if (isNaN(tabIndex) || tabIndex >= 0) {
10855
+ return true;
10856
+ }
10857
+ return false;
10858
+ };
10859
+ var sortByOrder = function sortByOrder2(candidates) {
10787
10860
  var regularTabbables = [];
10788
10861
  var orderedTabbables = [];
10789
- var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
10790
- candidates.forEach(function(candidate, i2) {
10791
- var candidateTabindex = getTabindex(candidate);
10862
+ candidates.forEach(function(item, i2) {
10863
+ var isScope = !!item.scope;
10864
+ var element = isScope ? item.scope : item;
10865
+ var candidateTabindex = getTabindex(element, isScope);
10866
+ var elements = isScope ? sortByOrder2(item.candidates) : element;
10792
10867
  if (candidateTabindex === 0) {
10793
- regularTabbables.push(candidate);
10868
+ isScope ? regularTabbables.push.apply(regularTabbables, elements) : regularTabbables.push(element);
10794
10869
  } else {
10795
10870
  orderedTabbables.push({
10796
10871
  documentOrder: i2,
10797
10872
  tabIndex: candidateTabindex,
10798
- node: candidate
10873
+ item,
10874
+ isScope,
10875
+ content: elements
10799
10876
  });
10800
10877
  }
10801
10878
  });
10802
- var tabbableNodes = orderedTabbables.sort(sortOrderedTabbables).map(function(a2) {
10803
- return a2.node;
10804
- }).concat(regularTabbables);
10805
- return tabbableNodes;
10879
+ return orderedTabbables.sort(sortOrderedTabbables).reduce(function(acc, sortable) {
10880
+ sortable.isScope ? acc.push.apply(acc, sortable.content) : acc.push(sortable.content);
10881
+ return acc;
10882
+ }, []).concat(regularTabbables);
10883
+ };
10884
+ var tabbable = function tabbable2(el, options) {
10885
+ options = options || {};
10886
+ var candidates;
10887
+ if (options.getShadowRoot) {
10888
+ candidates = getCandidatesIteratively([el], options.includeContainer, {
10889
+ filter: isNodeMatchingSelectorTabbable.bind(null, options),
10890
+ flatten: false,
10891
+ getShadowRoot: options.getShadowRoot,
10892
+ shadowRootFilter: isValidShadowRootTabbable
10893
+ });
10894
+ } else {
10895
+ candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
10896
+ }
10897
+ return sortByOrder(candidates);
10806
10898
  };
10807
10899
  var focusable = function focusable2(el, options) {
10808
10900
  options = options || {};
10809
- var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
10901
+ var candidates;
10902
+ if (options.getShadowRoot) {
10903
+ candidates = getCandidatesIteratively([el], options.includeContainer, {
10904
+ filter: isNodeMatchingSelectorFocusable.bind(null, options),
10905
+ flatten: true,
10906
+ getShadowRoot: options.getShadowRoot
10907
+ });
10908
+ } else {
10909
+ candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
10910
+ }
10810
10911
  return candidates;
10811
10912
  };
10913
+ var isTabbable = function isTabbable2(node, options) {
10914
+ options = options || {};
10915
+ if (!node) {
10916
+ throw new Error("No node provided");
10917
+ }
10918
+ if (matches.call(node, candidateSelector) === false) {
10919
+ return false;
10920
+ }
10921
+ return isNodeMatchingSelectorTabbable(options, node);
10922
+ };
10812
10923
  var focusableCandidateSelector = /* @__PURE__ */ candidateSelectors.concat("iframe").join(",");
10813
10924
  var isFocusable = function isFocusable2(node, options) {
10814
10925
  options = options || {};
@@ -10824,29 +10935,20 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10824
10935
  var keys = Object.keys(object);
10825
10936
  if (Object.getOwnPropertySymbols) {
10826
10937
  var symbols = Object.getOwnPropertySymbols(object);
10827
- if (enumerableOnly) {
10828
- symbols = symbols.filter(function(sym) {
10829
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
10830
- });
10831
- }
10832
- keys.push.apply(keys, symbols);
10938
+ enumerableOnly && (symbols = symbols.filter(function(sym) {
10939
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
10940
+ })), keys.push.apply(keys, symbols);
10833
10941
  }
10834
10942
  return keys;
10835
10943
  }
10836
10944
  function _objectSpread2(target) {
10837
10945
  for (var i2 = 1; i2 < arguments.length; i2++) {
10838
- var source = arguments[i2] != null ? arguments[i2] : {};
10839
- if (i2 % 2) {
10840
- ownKeys2(Object(source), true).forEach(function(key) {
10841
- _defineProperty(target, key, source[key]);
10842
- });
10843
- } else if (Object.getOwnPropertyDescriptors) {
10844
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
10845
- } else {
10846
- ownKeys2(Object(source)).forEach(function(key) {
10847
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
10848
- });
10849
- }
10946
+ var source = null != arguments[i2] ? arguments[i2] : {};
10947
+ i2 % 2 ? ownKeys2(Object(source), true).forEach(function(key) {
10948
+ _defineProperty(target, key, source[key]);
10949
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys2(Object(source)).forEach(function(key) {
10950
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
10951
+ });
10850
10952
  }
10851
10953
  return target;
10852
10954
  }
@@ -10921,64 +11023,103 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10921
11023
  }
10922
11024
  return typeof value === "function" ? value.apply(void 0, params) : value;
10923
11025
  };
11026
+ var getActualTarget = function getActualTarget2(event) {
11027
+ return event.target.shadowRoot && typeof event.composedPath === "function" ? event.composedPath()[0] : event.target;
11028
+ };
10924
11029
  var createFocusTrap = function createFocusTrap2(elements, userOptions) {
10925
- var doc = document;
11030
+ var doc = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.document) || document;
10926
11031
  var config = _objectSpread2({
10927
11032
  returnFocusOnDeactivate: true,
10928
11033
  escapeDeactivates: true,
10929
11034
  delayInitialFocus: true
10930
11035
  }, userOptions);
10931
11036
  var state = {
11037
+ // containers given to createFocusTrap()
11038
+ // @type {Array<HTMLElement>}
10932
11039
  containers: [],
11040
+ // list of objects identifying tabbable nodes in `containers` in the trap
11041
+ // NOTE: it's possible that a group has no tabbable nodes if nodes get removed while the trap
11042
+ // is active, but the trap should never get to a state where there isn't at least one group
11043
+ // with at least one tabbable node in it (that would lead to an error condition that would
11044
+ // result in an error being thrown)
11045
+ // @type {Array<{
11046
+ // container: HTMLElement,
11047
+ // tabbableNodes: Array<HTMLElement>, // empty if none
11048
+ // focusableNodes: Array<HTMLElement>, // empty if none
11049
+ // firstTabbableNode: HTMLElement|null,
11050
+ // lastTabbableNode: HTMLElement|null,
11051
+ // nextTabbableNode: (node: HTMLElement, forward: boolean) => HTMLElement|undefined
11052
+ // }>}
11053
+ containerGroups: [],
11054
+ // same order/length as `containers` list
11055
+ // references to objects in `containerGroups`, but only those that actually have
11056
+ // tabbable nodes in them
11057
+ // NOTE: same order as `containers` and `containerGroups`, but __not necessarily__
11058
+ // the same length
10933
11059
  tabbableGroups: [],
10934
11060
  nodeFocusedBeforeActivation: null,
10935
11061
  mostRecentlyFocusedNode: null,
10936
11062
  active: false,
10937
11063
  paused: false,
11064
+ // timer ID for when delayInitialFocus is true and initial focus in this trap
11065
+ // has been delayed during activation
10938
11066
  delayInitialFocusTimer: void 0
10939
11067
  };
10940
11068
  var trap;
10941
11069
  var getOption = function getOption2(configOverrideOptions, optionName, configOptionName) {
10942
11070
  return configOverrideOptions && configOverrideOptions[optionName] !== void 0 ? configOverrideOptions[optionName] : config[configOptionName || optionName];
10943
11071
  };
10944
- var containersContain = function containersContain2(element) {
10945
- return state.containers.some(function(container) {
10946
- return container.contains(element);
11072
+ var findContainerIndex = function findContainerIndex2(element) {
11073
+ return state.containerGroups.findIndex(function(_ref) {
11074
+ var container = _ref.container, tabbableNodes = _ref.tabbableNodes;
11075
+ return container.contains(element) || // fall back to explicit tabbable search which will take into consideration any
11076
+ // web components if the `tabbableOptions.getShadowRoot` option was used for
11077
+ // the trap, enabling shadow DOM support in tabbable (`Node.contains()` doesn't
11078
+ // look inside web components even if open)
11079
+ tabbableNodes.find(function(node) {
11080
+ return node === element;
11081
+ });
10947
11082
  });
10948
11083
  };
10949
11084
  var getNodeForOption = function getNodeForOption2(optionName) {
10950
11085
  var optionValue = config[optionName];
11086
+ if (typeof optionValue === "function") {
11087
+ for (var _len2 = arguments.length, params = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
11088
+ params[_key2 - 1] = arguments[_key2];
11089
+ }
11090
+ optionValue = optionValue.apply(void 0, params);
11091
+ }
11092
+ if (optionValue === true) {
11093
+ optionValue = void 0;
11094
+ }
10951
11095
  if (!optionValue) {
10952
- return null;
11096
+ if (optionValue === void 0 || optionValue === false) {
11097
+ return optionValue;
11098
+ }
11099
+ throw new Error("`".concat(optionName, "` was specified but was not a node, or did not return a node"));
10953
11100
  }
10954
11101
  var node = optionValue;
10955
11102
  if (typeof optionValue === "string") {
10956
11103
  node = doc.querySelector(optionValue);
10957
11104
  if (!node) {
10958
- throw new Error("`".concat(optionName, "` refers to no known node"));
10959
- }
10960
- }
10961
- if (typeof optionValue === "function") {
10962
- node = optionValue();
10963
- if (!node) {
10964
- throw new Error("`".concat(optionName, "` did not return a node"));
11105
+ throw new Error("`".concat(optionName, "` as selector refers to no known node"));
10965
11106
  }
10966
11107
  }
10967
11108
  return node;
10968
11109
  };
10969
11110
  var getInitialFocusNode = function getInitialFocusNode2() {
10970
- var node;
10971
- if (getOption({}, "initialFocus") === false) {
11111
+ var node = getNodeForOption("initialFocus");
11112
+ if (node === false) {
10972
11113
  return false;
10973
11114
  }
10974
- if (getNodeForOption("initialFocus") !== null) {
10975
- node = getNodeForOption("initialFocus");
10976
- } else if (containersContain(doc.activeElement)) {
10977
- node = doc.activeElement;
10978
- } else {
10979
- var firstTabbableGroup = state.tabbableGroups[0];
10980
- var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
10981
- node = firstTabbableNode || getNodeForOption("fallbackFocus");
11115
+ if (node === void 0) {
11116
+ if (findContainerIndex(doc.activeElement) >= 0) {
11117
+ node = doc.activeElement;
11118
+ } else {
11119
+ var firstTabbableGroup = state.tabbableGroups[0];
11120
+ var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
11121
+ node = firstTabbableNode || getNodeForOption("fallbackFocus");
11122
+ }
10982
11123
  }
10983
11124
  if (!node) {
10984
11125
  throw new Error("Your focus-trap needs to have at least one focusable element");
@@ -10986,18 +11127,44 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
10986
11127
  return node;
10987
11128
  };
10988
11129
  var updateTabbableNodes = function updateTabbableNodes2() {
10989
- state.tabbableGroups = state.containers.map(function(container) {
10990
- var tabbableNodes = tabbable(container);
10991
- if (tabbableNodes.length > 0) {
10992
- return {
10993
- container,
10994
- firstTabbableNode: tabbableNodes[0],
10995
- lastTabbableNode: tabbableNodes[tabbableNodes.length - 1]
10996
- };
10997
- }
10998
- return void 0;
10999
- }).filter(function(group) {
11000
- return !!group;
11130
+ state.containerGroups = state.containers.map(function(container) {
11131
+ var tabbableNodes = tabbable(container, config.tabbableOptions);
11132
+ var focusableNodes = focusable(container, config.tabbableOptions);
11133
+ return {
11134
+ container,
11135
+ tabbableNodes,
11136
+ focusableNodes,
11137
+ firstTabbableNode: tabbableNodes.length > 0 ? tabbableNodes[0] : null,
11138
+ lastTabbableNode: tabbableNodes.length > 0 ? tabbableNodes[tabbableNodes.length - 1] : null,
11139
+ /**
11140
+ * Finds the __tabbable__ node that follows the given node in the specified direction,
11141
+ * in this container, if any.
11142
+ * @param {HTMLElement} node
11143
+ * @param {boolean} [forward] True if going in forward tab order; false if going
11144
+ * in reverse.
11145
+ * @returns {HTMLElement|undefined} The next tabbable node, if any.
11146
+ */
11147
+ nextTabbableNode: function nextTabbableNode(node) {
11148
+ var forward = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
11149
+ var nodeIdx = focusableNodes.findIndex(function(n2) {
11150
+ return n2 === node;
11151
+ });
11152
+ if (nodeIdx < 0) {
11153
+ return void 0;
11154
+ }
11155
+ if (forward) {
11156
+ return focusableNodes.slice(nodeIdx + 1).find(function(n2) {
11157
+ return isTabbable(n2, config.tabbableOptions);
11158
+ });
11159
+ }
11160
+ return focusableNodes.slice(0, nodeIdx).reverse().find(function(n2) {
11161
+ return isTabbable(n2, config.tabbableOptions);
11162
+ });
11163
+ }
11164
+ };
11165
+ });
11166
+ state.tabbableGroups = state.containerGroups.filter(function(group) {
11167
+ return group.tabbableNodes.length > 0;
11001
11168
  });
11002
11169
  if (state.tabbableGroups.length <= 0 && !getNodeForOption("fallbackFocus")) {
11003
11170
  throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");
@@ -11023,16 +11190,28 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11023
11190
  }
11024
11191
  };
11025
11192
  var getReturnFocusNode = function getReturnFocusNode2(previousActiveElement) {
11026
- var node = getNodeForOption("setReturnFocus");
11027
- return node ? node : previousActiveElement;
11193
+ var node = getNodeForOption("setReturnFocus", previousActiveElement);
11194
+ return node ? node : node === false ? false : previousActiveElement;
11028
11195
  };
11029
11196
  var checkPointerDown = function checkPointerDown2(e2) {
11030
- if (containersContain(e2.target)) {
11197
+ var target = getActualTarget(e2);
11198
+ if (findContainerIndex(target) >= 0) {
11031
11199
  return;
11032
11200
  }
11033
11201
  if (valueOrHandler(config.clickOutsideDeactivates, e2)) {
11034
11202
  trap.deactivate({
11035
- returnFocus: config.returnFocusOnDeactivate && !isFocusable(e2.target)
11203
+ // if, on deactivation, we should return focus to the node originally-focused
11204
+ // when the trap was activated (or the configured `setReturnFocus` node),
11205
+ // then assume it's also OK to return focus to the outside node that was
11206
+ // just clicked, causing deactivation, as long as that node is focusable;
11207
+ // if it isn't focusable, then return focus to the original node focused
11208
+ // on activation (or the configured `setReturnFocus` node)
11209
+ // NOTE: by setting `returnFocus: false`, deactivate() will do nothing,
11210
+ // which will result in the outside click setting focus to the node
11211
+ // that was clicked, whether it's focusable or not; by setting
11212
+ // `returnFocus: true`, we'll attempt to re-focus the node originally-focused
11213
+ // on activation (or the configured `setReturnFocus` node)
11214
+ returnFocus: config.returnFocusOnDeactivate && !isFocusable(target, config.tabbableOptions)
11036
11215
  });
11037
11216
  return;
11038
11217
  }
@@ -11042,10 +11221,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11042
11221
  e2.preventDefault();
11043
11222
  };
11044
11223
  var checkFocusIn = function checkFocusIn2(e2) {
11045
- var targetContained = containersContain(e2.target);
11046
- if (targetContained || e2.target instanceof Document) {
11224
+ var target = getActualTarget(e2);
11225
+ var targetContained = findContainerIndex(target) >= 0;
11226
+ if (targetContained || target instanceof Document) {
11047
11227
  if (targetContained) {
11048
- state.mostRecentlyFocusedNode = e2.target;
11228
+ state.mostRecentlyFocusedNode = target;
11049
11229
  }
11050
11230
  } else {
11051
11231
  e2.stopImmediatePropagation();
@@ -11053,13 +11233,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11053
11233
  }
11054
11234
  };
11055
11235
  var checkTab = function checkTab2(e2) {
11236
+ var target = getActualTarget(e2);
11056
11237
  updateTabbableNodes();
11057
11238
  var destinationNode = null;
11058
11239
  if (state.tabbableGroups.length > 0) {
11059
- var containerIndex = findIndex(state.tabbableGroups, function(_ref) {
11060
- var container = _ref.container;
11061
- return container.contains(e2.target);
11062
- });
11240
+ var containerIndex = findContainerIndex(target);
11241
+ var containerGroup = containerIndex >= 0 ? state.containerGroups[containerIndex] : void 0;
11063
11242
  if (containerIndex < 0) {
11064
11243
  if (e2.shiftKey) {
11065
11244
  destinationNode = state.tabbableGroups[state.tabbableGroups.length - 1].lastTabbableNode;
@@ -11069,9 +11248,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11069
11248
  } else if (e2.shiftKey) {
11070
11249
  var startOfGroupIndex = findIndex(state.tabbableGroups, function(_ref2) {
11071
11250
  var firstTabbableNode = _ref2.firstTabbableNode;
11072
- return e2.target === firstTabbableNode;
11251
+ return target === firstTabbableNode;
11073
11252
  });
11074
- if (startOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e2.target) {
11253
+ if (startOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target, false))) {
11075
11254
  startOfGroupIndex = containerIndex;
11076
11255
  }
11077
11256
  if (startOfGroupIndex >= 0) {
@@ -11082,9 +11261,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11082
11261
  } else {
11083
11262
  var lastOfGroupIndex = findIndex(state.tabbableGroups, function(_ref3) {
11084
11263
  var lastTabbableNode = _ref3.lastTabbableNode;
11085
- return e2.target === lastTabbableNode;
11264
+ return target === lastTabbableNode;
11086
11265
  });
11087
- if (lastOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e2.target) {
11266
+ if (lastOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target))) {
11088
11267
  lastOfGroupIndex = containerIndex;
11089
11268
  }
11090
11269
  if (lastOfGroupIndex >= 0) {
@@ -11102,7 +11281,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11102
11281
  }
11103
11282
  };
11104
11283
  var checkKey = function checkKey2(e2) {
11105
- if (isEscapeEvent(e2) && valueOrHandler(config.escapeDeactivates) !== false) {
11284
+ if (isEscapeEvent(e2) && valueOrHandler(config.escapeDeactivates, e2) !== false) {
11106
11285
  e2.preventDefault();
11107
11286
  trap.deactivate();
11108
11287
  return;
@@ -11113,10 +11292,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11113
11292
  }
11114
11293
  };
11115
11294
  var checkClick = function checkClick2(e2) {
11116
- if (valueOrHandler(config.clickOutsideDeactivates, e2)) {
11295
+ var target = getActualTarget(e2);
11296
+ if (findContainerIndex(target) >= 0) {
11117
11297
  return;
11118
11298
  }
11119
- if (containersContain(e2.target)) {
11299
+ if (valueOrHandler(config.clickOutsideDeactivates, e2)) {
11120
11300
  return;
11121
11301
  }
11122
11302
  if (valueOrHandler(config.allowOutsideClick, e2)) {
@@ -11164,6 +11344,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11164
11344
  return trap;
11165
11345
  };
11166
11346
  trap = {
11347
+ get active() {
11348
+ return state.active;
11349
+ },
11350
+ get paused() {
11351
+ return state.paused;
11352
+ },
11167
11353
  activate: function activate(activateOptions) {
11168
11354
  if (state.active) {
11169
11355
  return this;
@@ -11200,19 +11386,24 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11200
11386
  if (!state.active) {
11201
11387
  return this;
11202
11388
  }
11389
+ var options = _objectSpread2({
11390
+ onDeactivate: config.onDeactivate,
11391
+ onPostDeactivate: config.onPostDeactivate,
11392
+ checkCanReturnFocus: config.checkCanReturnFocus
11393
+ }, deactivateOptions);
11203
11394
  clearTimeout(state.delayInitialFocusTimer);
11204
11395
  state.delayInitialFocusTimer = void 0;
11205
11396
  removeListeners();
11206
11397
  state.active = false;
11207
11398
  state.paused = false;
11208
11399
  activeFocusTraps.deactivateTrap(trap);
11209
- var onDeactivate = getOption(deactivateOptions, "onDeactivate");
11210
- var onPostDeactivate = getOption(deactivateOptions, "onPostDeactivate");
11211
- var checkCanReturnFocus = getOption(deactivateOptions, "checkCanReturnFocus");
11400
+ var onDeactivate = getOption(options, "onDeactivate");
11401
+ var onPostDeactivate = getOption(options, "onPostDeactivate");
11402
+ var checkCanReturnFocus = getOption(options, "checkCanReturnFocus");
11403
+ var returnFocus = getOption(options, "returnFocus", "returnFocusOnDeactivate");
11212
11404
  if (onDeactivate) {
11213
11405
  onDeactivate();
11214
11406
  }
11215
- var returnFocus = getOption(deactivateOptions, "returnFocus", "returnFocusOnDeactivate");
11216
11407
  var finishDeactivation = function finishDeactivation2() {
11217
11408
  delay(function() {
11218
11409
  if (returnFocus) {
@@ -11372,55 +11563,61 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
11372
11563
  }
11373
11564
  };
11374
11565
  });
11375
- Alpine3.directive("trap", Alpine3.skipDuringClone((el, { expression, modifiers }, { effect: effect7, evaluateLater: evaluateLater2, cleanup: cleanup2 }) => {
11376
- let evaluator = evaluateLater2(expression);
11377
- let oldValue = false;
11378
- let options = {
11379
- escapeDeactivates: false,
11380
- allowOutsideClick: true,
11381
- fallbackFocus: () => el
11382
- };
11383
- let autofocusEl = el.querySelector("[autofocus]");
11384
- if (autofocusEl)
11385
- options.initialFocus = autofocusEl;
11386
- let trap = createFocusTrap(el, options);
11387
- let undoInert = () => {
11388
- };
11389
- let undoDisableScrolling = () => {
11390
- };
11391
- const releaseFocus = () => {
11392
- undoInert();
11393
- undoInert = () => {
11566
+ Alpine3.directive("trap", Alpine3.skipDuringClone(
11567
+ (el, { expression, modifiers }, { effect: effect7, evaluateLater: evaluateLater2, cleanup: cleanup2 }) => {
11568
+ let evaluator = evaluateLater2(expression);
11569
+ let oldValue = false;
11570
+ let options = {
11571
+ escapeDeactivates: false,
11572
+ allowOutsideClick: true,
11573
+ fallbackFocus: () => el
11394
11574
  };
11395
- undoDisableScrolling();
11396
- undoDisableScrolling = () => {
11575
+ let autofocusEl = el.querySelector("[autofocus]");
11576
+ if (autofocusEl)
11577
+ options.initialFocus = autofocusEl;
11578
+ let trap = createFocusTrap(el, options);
11579
+ let undoInert = () => {
11397
11580
  };
11398
- trap.deactivate({
11399
- returnFocus: !modifiers.includes("noreturn")
11400
- });
11401
- };
11402
- effect7(() => evaluator((value) => {
11403
- if (oldValue === value)
11404
- return;
11405
- if (value && !oldValue) {
11406
- setTimeout(() => {
11407
- if (modifiers.includes("inert"))
11408
- undoInert = setInert(el);
11409
- if (modifiers.includes("noscroll"))
11410
- undoDisableScrolling = disableScrolling();
11411
- trap.activate();
11581
+ let undoDisableScrolling = () => {
11582
+ };
11583
+ const releaseFocus = () => {
11584
+ undoInert();
11585
+ undoInert = () => {
11586
+ };
11587
+ undoDisableScrolling();
11588
+ undoDisableScrolling = () => {
11589
+ };
11590
+ trap.deactivate({
11591
+ returnFocus: !modifiers.includes("noreturn")
11412
11592
  });
11413
- }
11414
- if (!value && oldValue) {
11415
- releaseFocus();
11416
- }
11417
- oldValue = !!value;
11418
- }));
11419
- cleanup2(releaseFocus);
11420
- }, (el, { expression, modifiers }, { evaluate: evaluate2 }) => {
11421
- if (modifiers.includes("inert") && evaluate2(expression))
11422
- setInert(el);
11423
- }));
11593
+ };
11594
+ effect7(() => evaluator((value) => {
11595
+ if (oldValue === value)
11596
+ return;
11597
+ if (value && !oldValue) {
11598
+ setTimeout(() => {
11599
+ if (modifiers.includes("inert"))
11600
+ undoInert = setInert(el);
11601
+ if (modifiers.includes("noscroll"))
11602
+ undoDisableScrolling = disableScrolling();
11603
+ trap.activate();
11604
+ });
11605
+ }
11606
+ if (!value && oldValue) {
11607
+ releaseFocus();
11608
+ }
11609
+ oldValue = !!value;
11610
+ }));
11611
+ cleanup2(releaseFocus);
11612
+ },
11613
+ // When cloning, we only want to add aria-hidden attributes to the
11614
+ // DOM and not try to actually trap, as trapping can mess with the
11615
+ // live DOM and isn't just isolated to the cloned DOM.
11616
+ (el, { expression, modifiers }, { evaluate: evaluate2 }) => {
11617
+ if (modifiers.includes("inert") && evaluate2(expression))
11618
+ setInert(el);
11619
+ }
11620
+ ));
11424
11621
  }
11425
11622
  function setInert(el) {
11426
11623
  let undos = [];
@@ -15390,12 +15587,18 @@ lodash/lodash.js:
15390
15587
  *)
15391
15588
 
15392
15589
  @alpinejs/focus/dist/module.esm.js:
15393
- (*!
15394
- * tabbable 5.2.1
15395
- * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
15396
- *)
15397
- (*!
15398
- * focus-trap 6.6.1
15399
- * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
15590
+ (*! Bundled license information:
15591
+
15592
+ tabbable/dist/index.esm.js:
15593
+ (*!
15594
+ * tabbable 5.3.3
15595
+ * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
15596
+ *)
15597
+
15598
+ focus-trap/dist/focus-trap.esm.js:
15599
+ (*!
15600
+ * focus-trap 6.9.4
15601
+ * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
15602
+ *)
15400
15603
  *)
15401
15604
  */