@primer/components 0.0.0-20211030175556 → 0.0.0-20211030175634

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 (248) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/dist/browser.esm.js +144 -137
  3. package/dist/browser.esm.js.map +1 -1
  4. package/dist/browser.umd.js +128 -121
  5. package/dist/browser.umd.js.map +1 -1
  6. package/lib/ActionList/Item.js +3 -3
  7. package/lib/ActionList/index.js +23 -12
  8. package/lib/ActionList2/Item.js +3 -1
  9. package/lib/ActionList2/List.js +1 -2
  10. package/lib/ActionList2/Selection.js +3 -1
  11. package/lib/ActionList2/index.js +41 -23
  12. package/lib/AnchoredOverlay/index.js +12 -4
  13. package/lib/Autocomplete/Autocomplete.d.ts +1 -0
  14. package/lib/Autocomplete/AutocompleteInput.d.ts +1 -0
  15. package/lib/Autocomplete/index.js +14 -7
  16. package/lib/Button/Button.d.ts +1 -0
  17. package/lib/Button/ButtonClose.d.ts +2 -1
  18. package/lib/Button/ButtonDanger.d.ts +1 -0
  19. package/lib/Button/ButtonInvisible.d.ts +1 -0
  20. package/lib/Button/ButtonOutline.d.ts +1 -0
  21. package/lib/Button/ButtonPrimary.d.ts +1 -0
  22. package/lib/Button/index.js +70 -21
  23. package/lib/Checkbox.d.ts +29 -0
  24. package/lib/Checkbox.js +64 -0
  25. package/lib/CircleOcticon.d.ts +1 -0
  26. package/lib/Dialog.d.ts +3 -2
  27. package/lib/Dropdown.d.ts +4 -0
  28. package/lib/DropdownMenu/DropdownButton.d.ts +2 -1
  29. package/lib/DropdownMenu/index.js +20 -6
  30. package/lib/DropdownStyles.js +26 -18
  31. package/lib/FilterList.d.ts +1 -0
  32. package/lib/FilteredActionList/index.js +12 -4
  33. package/lib/NewButton/index.js +12 -5
  34. package/lib/NewButton/types.js +1 -2
  35. package/lib/Overlay.d.ts +5 -3
  36. package/lib/Pagination/index.js +12 -6
  37. package/lib/Portal/index.js +16 -5
  38. package/lib/Position.d.ts +4 -4
  39. package/lib/SelectMenu/SelectMenu.d.ts +10 -4
  40. package/lib/SelectMenu/SelectMenuItem.d.ts +1 -1
  41. package/lib/SelectMenu/SelectMenuModal.d.ts +1 -1
  42. package/lib/SelectMenu/hooks/useKeyboardNav.js +96 -80
  43. package/lib/SelectMenu/index.js +14 -7
  44. package/lib/SelectPanel/index.js +12 -4
  45. package/lib/TextInputWithTokens.d.ts +1 -0
  46. package/lib/Token/AvatarToken.d.ts +1 -1
  47. package/lib/Token/IssueLabelToken.d.ts +1 -1
  48. package/lib/Token/Token.d.ts +1 -1
  49. package/lib/Token/index.js +30 -11
  50. package/lib/behaviors/anchoredPosition.js +234 -205
  51. package/lib/behaviors/focusTrap.js +157 -121
  52. package/lib/behaviors/focusZone.js +509 -434
  53. package/lib/behaviors/scrollIntoViewingArea.js +35 -18
  54. package/lib/constants.js +43 -39
  55. package/lib/drafts.js +30 -20
  56. package/lib/hooks/index.js +60 -16
  57. package/lib/hooks/useAnchoredPosition.js +40 -32
  58. package/lib/hooks/useCombinedRefs.js +36 -32
  59. package/lib/hooks/useDialog.js +96 -72
  60. package/lib/hooks/useFocusTrap.js +60 -43
  61. package/lib/hooks/useFocusZone.js +50 -54
  62. package/lib/hooks/useOnEscapePress.js +36 -25
  63. package/lib/hooks/useOpenAndCloseFocus.js +34 -22
  64. package/lib/hooks/useProvidedRefOrCreate.js +14 -10
  65. package/lib/hooks/useProvidedStateOrCreate.js +16 -13
  66. package/lib/hooks/useRenderForcingRef.js +17 -13
  67. package/lib/hooks/useResizeObserver.js +18 -15
  68. package/lib/hooks/useSafeTimeout.js +30 -22
  69. package/lib/hooks/useScrollFlash.js +23 -16
  70. package/lib/index.d.ts +2 -0
  71. package/lib/index.js +652 -163
  72. package/lib/polyfills/eventListenerSignal.js +45 -37
  73. package/lib/sx.js +22 -10
  74. package/lib/theme-preval.js +3169 -64
  75. package/lib/theme.js +12 -3
  76. package/lib/utils/iterateFocusableElements.js +85 -63
  77. package/lib/utils/testing.d.ts +2 -1
  78. package/lib/utils/testing.js +29 -0
  79. package/lib/utils/theme.js +47 -33
  80. package/lib/utils/types/AriaRole.js +1 -2
  81. package/lib/utils/types/ComponentProps.js +1 -2
  82. package/lib/utils/types/Flatten.js +1 -2
  83. package/lib/utils/types/KeyPaths.js +1 -2
  84. package/lib/utils/types/MandateProps.js +1 -16
  85. package/lib/utils/types/Merge.js +1 -2
  86. package/lib/utils/types/index.js +69 -16
  87. package/lib/utils/uniqueId.js +8 -5
  88. package/lib/utils/use-force-update.js +14 -8
  89. package/lib/utils/useIsomorphicLayoutEffect.js +11 -8
  90. package/lib/utils/userAgent.js +12 -8
  91. package/lib-esm/ActionList/Item.js +3 -3
  92. package/lib-esm/ActionList2/Item.js +3 -1
  93. package/lib-esm/ActionList2/List.js +1 -2
  94. package/lib-esm/ActionList2/Selection.js +3 -1
  95. package/lib-esm/Autocomplete/Autocomplete.d.ts +1 -0
  96. package/lib-esm/Autocomplete/AutocompleteInput.d.ts +1 -0
  97. package/lib-esm/Button/Button.d.ts +1 -0
  98. package/lib-esm/Button/ButtonClose.d.ts +2 -1
  99. package/lib-esm/Button/ButtonDanger.d.ts +1 -0
  100. package/lib-esm/Button/ButtonInvisible.d.ts +1 -0
  101. package/lib-esm/Button/ButtonOutline.d.ts +1 -0
  102. package/lib-esm/Button/ButtonPrimary.d.ts +1 -0
  103. package/lib-esm/Checkbox.d.ts +29 -0
  104. package/lib-esm/Checkbox.js +44 -0
  105. package/lib-esm/CircleOcticon.d.ts +1 -0
  106. package/lib-esm/Dialog.d.ts +3 -2
  107. package/lib-esm/Dropdown.d.ts +4 -0
  108. package/lib-esm/DropdownMenu/DropdownButton.d.ts +2 -1
  109. package/lib-esm/FilterList.d.ts +1 -0
  110. package/lib-esm/Overlay.d.ts +5 -3
  111. package/lib-esm/Position.d.ts +4 -4
  112. package/lib-esm/SelectMenu/SelectMenu.d.ts +10 -4
  113. package/lib-esm/SelectMenu/SelectMenuItem.d.ts +1 -1
  114. package/lib-esm/SelectMenu/SelectMenuModal.d.ts +1 -1
  115. package/lib-esm/TextInputWithTokens.d.ts +1 -0
  116. package/lib-esm/Token/AvatarToken.d.ts +1 -1
  117. package/lib-esm/Token/IssueLabelToken.d.ts +1 -1
  118. package/lib-esm/Token/Token.d.ts +1 -1
  119. package/lib-esm/index.d.ts +2 -0
  120. package/lib-esm/index.js +1 -0
  121. package/lib-esm/theme-preval.js +446 -0
  122. package/lib-esm/utils/testing.d.ts +2 -1
  123. package/lib-esm/utils/testing.js +24 -0
  124. package/package.json +4 -5
  125. package/lib/ActionList/Divider.jsx +0 -29
  126. package/lib/ActionList/Group.jsx +0 -23
  127. package/lib/ActionList/Header.jsx +0 -66
  128. package/lib/ActionList/Item.jsx +0 -288
  129. package/lib/ActionList/List.jsx +0 -138
  130. package/lib/ActionList2/Description.jsx +0 -29
  131. package/lib/ActionList2/Divider.jsx +0 -22
  132. package/lib/ActionList2/Group.jsx +0 -54
  133. package/lib/ActionList2/Header.d.ts +0 -26
  134. package/lib/ActionList2/Header.js +0 -55
  135. package/lib/ActionList2/Header.jsx +0 -36
  136. package/lib/ActionList2/Item.jsx +0 -174
  137. package/lib/ActionList2/LinkItem.jsx +0 -28
  138. package/lib/ActionList2/List.jsx +0 -41
  139. package/lib/ActionList2/Selection.jsx +0 -50
  140. package/lib/ActionList2/Visuals.jsx +0 -48
  141. package/lib/ActionMenu.jsx +0 -73
  142. package/lib/AnchoredOverlay/AnchoredOverlay.jsx +0 -100
  143. package/lib/Autocomplete/Autocomplete.jsx +0 -100
  144. package/lib/Autocomplete/AutocompleteContext.jsx +0 -5
  145. package/lib/Autocomplete/AutocompleteInput.jsx +0 -113
  146. package/lib/Autocomplete/AutocompleteMenu.jsx +0 -190
  147. package/lib/Autocomplete/AutocompleteOverlay.jsx +0 -55
  148. package/lib/Avatar.jsx +0 -34
  149. package/lib/AvatarPair.jsx +0 -29
  150. package/lib/AvatarStack.jsx +0 -151
  151. package/lib/BaseStyles.jsx +0 -65
  152. package/lib/BorderBox.jsx +0 -18
  153. package/lib/Box.jsx +0 -10
  154. package/lib/BranchName.jsx +0 -20
  155. package/lib/Breadcrumbs.jsx +0 -71
  156. package/lib/Button/Button.jsx +0 -40
  157. package/lib/Button/ButtonBase.jsx +0 -33
  158. package/lib/Button/ButtonClose.jsx +0 -53
  159. package/lib/Button/ButtonDanger.jsx +0 -43
  160. package/lib/Button/ButtonGroup.jsx +0 -55
  161. package/lib/Button/ButtonInvisible.jsx +0 -32
  162. package/lib/Button/ButtonOutline.jsx +0 -43
  163. package/lib/Button/ButtonPrimary.jsx +0 -42
  164. package/lib/Button/ButtonStyles.jsx +0 -37
  165. package/lib/Button/ButtonTableList.jsx +0 -46
  166. package/lib/Caret.jsx +0 -93
  167. package/lib/CircleBadge.jsx +0 -42
  168. package/lib/CircleOcticon.jsx +0 -21
  169. package/lib/CounterLabel.jsx +0 -43
  170. package/lib/Details.jsx +0 -21
  171. package/lib/Dialog/ConfirmationDialog.jsx +0 -146
  172. package/lib/Dialog/Dialog.jsx +0 -279
  173. package/lib/Dialog.jsx +0 -129
  174. package/lib/Dropdown.jsx +0 -131
  175. package/lib/DropdownMenu/DropdownButton.jsx +0 -14
  176. package/lib/DropdownMenu/DropdownMenu.jsx +0 -70
  177. package/lib/FilterList.jsx +0 -59
  178. package/lib/FilteredActionList/FilteredActionList.jsx +0 -100
  179. package/lib/FilteredSearch.jsx +0 -28
  180. package/lib/Flash.jsx +0 -69
  181. package/lib/Flex.jsx +0 -15
  182. package/lib/FormGroup.jsx +0 -22
  183. package/lib/Grid.jsx +0 -15
  184. package/lib/Header.jsx +0 -83
  185. package/lib/Heading.jsx +0 -21
  186. package/lib/Label.jsx +0 -82
  187. package/lib/LabelGroup.jsx +0 -18
  188. package/lib/Link.jsx +0 -36
  189. package/lib/NewButton/button-counter.jsx +0 -14
  190. package/lib/NewButton/button.jsx +0 -279
  191. package/lib/Overlay.jsx +0 -154
  192. package/lib/Pagehead.jsx +0 -17
  193. package/lib/Pagination/Pagination.jsx +0 -161
  194. package/lib/Pagination/model.jsx +0 -174
  195. package/lib/PointerBox.jsx +0 -25
  196. package/lib/Popover.jsx +0 -202
  197. package/lib/Portal/Portal.jsx +0 -79
  198. package/lib/Position.jsx +0 -46
  199. package/lib/ProgressBar.jsx +0 -39
  200. package/lib/SelectMenu/SelectMenu.jsx +0 -112
  201. package/lib/SelectMenu/SelectMenuContext.jsx +0 -5
  202. package/lib/SelectMenu/SelectMenuDivider.jsx +0 -42
  203. package/lib/SelectMenu/SelectMenuFilter.jsx +0 -58
  204. package/lib/SelectMenu/SelectMenuFooter.jsx +0 -45
  205. package/lib/SelectMenu/SelectMenuHeader.jsx +0 -42
  206. package/lib/SelectMenu/SelectMenuItem.jsx +0 -142
  207. package/lib/SelectMenu/SelectMenuList.jsx +0 -59
  208. package/lib/SelectMenu/SelectMenuLoadingAnimation.jsx +0 -22
  209. package/lib/SelectMenu/SelectMenuModal.jsx +0 -118
  210. package/lib/SelectMenu/SelectMenuTab.jsx +0 -92
  211. package/lib/SelectMenu/SelectMenuTabPanel.jsx +0 -42
  212. package/lib/SelectMenu/SelectMenuTabs.jsx +0 -57
  213. package/lib/SelectPanel/SelectPanel.jsx +0 -105
  214. package/lib/SideNav.jsx +0 -173
  215. package/lib/Spinner.jsx +0 -35
  216. package/lib/StateLabel.jsx +0 -93
  217. package/lib/StyledOcticon.jsx +0 -18
  218. package/lib/SubNav.jsx +0 -101
  219. package/lib/TabNav.jsx +0 -58
  220. package/lib/Text.jsx +0 -14
  221. package/lib/TextInput.jsx +0 -23
  222. package/lib/TextInputWithTokens.jsx +0 -218
  223. package/lib/ThemeProvider.jsx +0 -130
  224. package/lib/Timeline.jsx +0 -123
  225. package/lib/Token/AvatarToken.jsx +0 -54
  226. package/lib/Token/IssueLabelToken.jsx +0 -125
  227. package/lib/Token/Token.jsx +0 -103
  228. package/lib/Token/TokenBase.jsx +0 -88
  229. package/lib/Token/_RemoveTokenButton.jsx +0 -108
  230. package/lib/Token/_TokenTextContainer.jsx +0 -49
  231. package/lib/Tooltip.jsx +0 -246
  232. package/lib/Truncate.jsx +0 -24
  233. package/lib/UnderlineNav.jsx +0 -88
  234. package/lib/_TextInputWrapper.jsx +0 -120
  235. package/lib/_UnstyledTextInput.jsx +0 -22
  236. package/lib/hooks/useDetails.jsx +0 -39
  237. package/lib/hooks/useOnOutsideClick.jsx +0 -61
  238. package/lib/hooks/useOverlay.jsx +0 -15
  239. package/lib/utils/create-slots.jsx +0 -65
  240. package/lib/utils/deprecate.jsx +0 -59
  241. package/lib/utils/isNumeric.jsx +0 -7
  242. package/lib/utils/ssr.jsx +0 -6
  243. package/lib/utils/test-deprecations.jsx +0 -20
  244. package/lib/utils/test-helpers.jsx +0 -8
  245. package/lib/utils/test-matchers.jsx +0 -100
  246. package/lib/utils/testing.jsx +0 -206
  247. package/lib-esm/ActionList2/Header.d.ts +0 -26
  248. package/lib-esm/ActionList2/Header.js +0 -44
@@ -1,25 +1,34 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.focusTrap = void 0;
4
- const iterateFocusableElements_1 = require("../utils/iterateFocusableElements");
5
- const eventListenerSignal_1 = require("../polyfills/eventListenerSignal");
6
- eventListenerSignal_1.polyfill();
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.focusTrap = focusTrap;
7
+
8
+ var _iterateFocusableElements = require("../utils/iterateFocusableElements");
9
+
10
+ var _eventListenerSignal = require("../polyfills/eventListenerSignal");
11
+
12
+ (0, _eventListenerSignal.polyfill)();
7
13
  const suspendedTrapStack = [];
8
14
  let activeTrap = undefined;
15
+
9
16
  function tryReactivate() {
10
- const trapToReactivate = suspendedTrapStack.pop();
11
- if (trapToReactivate) {
12
- focusTrap(trapToReactivate.container, trapToReactivate.initialFocus, trapToReactivate.originalSignal);
13
- }
14
- }
15
- // @todo If AbortController.prototype.follow is ever implemented, that
17
+ const trapToReactivate = suspendedTrapStack.pop();
18
+
19
+ if (trapToReactivate) {
20
+ focusTrap(trapToReactivate.container, trapToReactivate.initialFocus, trapToReactivate.originalSignal);
21
+ }
22
+ } // @todo If AbortController.prototype.follow is ever implemented, that
16
23
  // could replace this function. @see https://github.com/whatwg/dom/issues/920
24
+
25
+
17
26
  function followSignal(signal) {
18
- const controller = new AbortController();
19
- signal.addEventListener('abort', () => {
20
- controller.abort();
21
- });
22
- return controller;
27
+ const controller = new AbortController();
28
+ signal.addEventListener('abort', () => {
29
+ controller.abort();
30
+ });
31
+ return controller;
23
32
  }
24
33
  /**
25
34
  * Returns the first focusable child of `container`. If `lastChild` is true,
@@ -27,117 +36,144 @@ function followSignal(signal) {
27
36
  * @param container
28
37
  * @param lastChild
29
38
  */
39
+
40
+
30
41
  function getFocusableChild(container, lastChild = false) {
31
- return iterateFocusableElements_1.iterateFocusableElements(container, { reverse: lastChild, strict: true, onlyTabbable: true }).next().value;
42
+ return (0, _iterateFocusableElements.iterateFocusableElements)(container, {
43
+ reverse: lastChild,
44
+ strict: true,
45
+ onlyTabbable: true
46
+ }).next().value;
32
47
  }
48
+ /**
49
+ * Traps focus within the given container.
50
+ * @param container The container in which to trap focus
51
+ * @returns AbortController - call `.abort()` to disable the focus trap
52
+ */
53
+
54
+
33
55
  function focusTrap(container, initialFocus, abortSignal) {
34
- // Set up an abort controller if a signal was not passed in
35
- const controller = new AbortController();
36
- const signal = abortSignal ?? controller.signal;
37
- container.setAttribute('data-focus-trap', 'active');
38
- let lastFocusedChild = undefined;
39
- // Ensure focus remains in the trap zone by checking that a given recently-focused
40
- // element is inside the trap zone. If it isn't, redirect focus to a suitable
41
- // element within the trap zone. If need to redirect focus and a suitable element
42
- // is not found, focus the container.
43
- function ensureTrapZoneHasFocus(focusedElement) {
44
- if (focusedElement instanceof HTMLElement && document.contains(container)) {
45
- if (container.contains(focusedElement)) {
46
- // If a child of the trap zone was focused, remember it
47
- lastFocusedChild = focusedElement;
48
- return;
49
- }
50
- else {
51
- if (lastFocusedChild && iterateFocusableElements_1.isTabbable(lastFocusedChild) && container.contains(lastFocusedChild)) {
52
- lastFocusedChild.focus();
53
- return;
54
- }
55
- else if (initialFocus && container.contains(initialFocus)) {
56
- initialFocus.focus();
57
- return;
58
- }
59
- else {
60
- // Ensure the container is focusable:
61
- // - Either the container already has a `tabIndex`
62
- // - Or provide a temporary `tabIndex`
63
- const containerNeedsTemporaryTabIndex = container.getAttribute('tabindex') === null;
64
- if (containerNeedsTemporaryTabIndex) {
65
- container.setAttribute('tabindex', '-1');
66
- }
67
- // Focus the container.
68
- container.focus();
69
- // If a temporary `tabIndex` was provided, remove it.
70
- if (containerNeedsTemporaryTabIndex) {
71
- // Once focus has moved from the container to a child within the FocusTrap,
72
- // the container can be made un-refocusable by removing `tabIndex`.
73
- container.addEventListener('blur', () => container.removeAttribute('tabindex'), { once: true });
74
- // NB: If `tabIndex` was removed *before* `blur`, then certain browsers (e.g. Chrome)
75
- // would consider `body` the `activeElement`, and as a result, keyboard navigation
76
- // between children would break, since `body` is outside the `FocusTrap`.
77
- }
78
- return;
79
- }
80
- }
56
+ // Set up an abort controller if a signal was not passed in
57
+ const controller = new AbortController();
58
+ const signal = abortSignal !== null && abortSignal !== void 0 ? abortSignal : controller.signal;
59
+ container.setAttribute('data-focus-trap', 'active');
60
+ let lastFocusedChild = undefined; // Ensure focus remains in the trap zone by checking that a given recently-focused
61
+ // element is inside the trap zone. If it isn't, redirect focus to a suitable
62
+ // element within the trap zone. If need to redirect focus and a suitable element
63
+ // is not found, focus the container.
64
+
65
+ function ensureTrapZoneHasFocus(focusedElement) {
66
+ if (focusedElement instanceof HTMLElement && document.contains(container)) {
67
+ if (container.contains(focusedElement)) {
68
+ // If a child of the trap zone was focused, remember it
69
+ lastFocusedChild = focusedElement;
70
+ return;
71
+ } else {
72
+ if (lastFocusedChild && (0, _iterateFocusableElements.isTabbable)(lastFocusedChild) && container.contains(lastFocusedChild)) {
73
+ lastFocusedChild.focus();
74
+ return;
75
+ } else if (initialFocus && container.contains(initialFocus)) {
76
+ initialFocus.focus();
77
+ return;
78
+ } else {
79
+ // Ensure the container is focusable:
80
+ // - Either the container already has a `tabIndex`
81
+ // - Or provide a temporary `tabIndex`
82
+ const containerNeedsTemporaryTabIndex = container.getAttribute('tabindex') === null;
83
+
84
+ if (containerNeedsTemporaryTabIndex) {
85
+ container.setAttribute('tabindex', '-1');
86
+ } // Focus the container.
87
+
88
+
89
+ container.focus(); // If a temporary `tabIndex` was provided, remove it.
90
+
91
+ if (containerNeedsTemporaryTabIndex) {
92
+ // Once focus has moved from the container to a child within the FocusTrap,
93
+ // the container can be made un-refocusable by removing `tabIndex`.
94
+ container.addEventListener('blur', () => container.removeAttribute('tabindex'), {
95
+ once: true
96
+ }); // NB: If `tabIndex` was removed *before* `blur`, then certain browsers (e.g. Chrome)
97
+ // would consider `body` the `activeElement`, and as a result, keyboard navigation
98
+ // between children would break, since `body` is outside the `FocusTrap`.
99
+ }
100
+
101
+ return;
81
102
  }
103
+ }
82
104
  }
83
- const wrappingController = followSignal(signal);
84
- container.addEventListener('keydown', event => {
85
- if (event.key !== 'Tab' || event.defaultPrevented) {
86
- return;
87
- }
88
- const { target } = event;
89
- const firstFocusableChild = getFocusableChild(container);
90
- const lastFocusableChild = getFocusableChild(container, true);
91
- if (target === firstFocusableChild && event.shiftKey) {
92
- event.preventDefault();
93
- lastFocusableChild?.focus();
94
- }
95
- else if (target === lastFocusableChild && !event.shiftKey) {
96
- event.preventDefault();
97
- firstFocusableChild?.focus();
98
- }
99
- }, { signal: wrappingController.signal });
100
- if (activeTrap) {
101
- const suspendedTrap = activeTrap;
102
- activeTrap.container.setAttribute('data-focus-trap', 'suspended');
103
- activeTrap.controller.abort();
104
- suspendedTrapStack.push(suspendedTrap);
105
+ }
106
+
107
+ const wrappingController = followSignal(signal);
108
+ container.addEventListener('keydown', event => {
109
+ if (event.key !== 'Tab' || event.defaultPrevented) {
110
+ return;
105
111
  }
106
- // When this trap is canceled, either by the user or by us for suspension
107
- wrappingController.signal.addEventListener('abort', () => {
108
- activeTrap = undefined;
109
- });
110
- // Only when user-canceled
111
- signal.addEventListener('abort', () => {
112
- container.removeAttribute('data-focus-trap');
113
- const suspendedTrapIndex = suspendedTrapStack.findIndex(t => t.container === container);
114
- if (suspendedTrapIndex >= 0) {
115
- suspendedTrapStack.splice(suspendedTrapIndex, 1);
116
- }
117
- tryReactivate();
118
- });
119
- // Prevent focus leaving the trap container
120
- document.addEventListener('focus', event => {
121
- ensureTrapZoneHasFocus(event.target);
122
- },
123
- // use capture to ensure we get all events. focus events do not bubble
124
- { signal: wrappingController.signal, capture: true });
125
- // focus the first element
126
- ensureTrapZoneHasFocus(document.activeElement);
127
- activeTrap = {
128
- container,
129
- controller: wrappingController,
130
- initialFocus,
131
- originalSignal: signal
132
- };
133
- // If we are activating a focus trap for a container that was previously
134
- // suspended, just remove it from the suspended list.
112
+
113
+ const {
114
+ target
115
+ } = event;
116
+ const firstFocusableChild = getFocusableChild(container);
117
+ const lastFocusableChild = getFocusableChild(container, true);
118
+
119
+ if (target === firstFocusableChild && event.shiftKey) {
120
+ event.preventDefault();
121
+ lastFocusableChild === null || lastFocusableChild === void 0 ? void 0 : lastFocusableChild.focus();
122
+ } else if (target === lastFocusableChild && !event.shiftKey) {
123
+ event.preventDefault();
124
+ firstFocusableChild === null || firstFocusableChild === void 0 ? void 0 : firstFocusableChild.focus();
125
+ }
126
+ }, {
127
+ signal: wrappingController.signal
128
+ });
129
+
130
+ if (activeTrap) {
131
+ const suspendedTrap = activeTrap;
132
+ activeTrap.container.setAttribute('data-focus-trap', 'suspended');
133
+ activeTrap.controller.abort();
134
+ suspendedTrapStack.push(suspendedTrap);
135
+ } // When this trap is canceled, either by the user or by us for suspension
136
+
137
+
138
+ wrappingController.signal.addEventListener('abort', () => {
139
+ activeTrap = undefined;
140
+ }); // Only when user-canceled
141
+
142
+ signal.addEventListener('abort', () => {
143
+ container.removeAttribute('data-focus-trap');
135
144
  const suspendedTrapIndex = suspendedTrapStack.findIndex(t => t.container === container);
145
+
136
146
  if (suspendedTrapIndex >= 0) {
137
- suspendedTrapStack.splice(suspendedTrapIndex, 1);
138
- }
139
- if (!abortSignal) {
140
- return controller;
147
+ suspendedTrapStack.splice(suspendedTrapIndex, 1);
141
148
  }
142
- }
143
- exports.focusTrap = focusTrap;
149
+
150
+ tryReactivate();
151
+ }); // Prevent focus leaving the trap container
152
+
153
+ document.addEventListener('focus', event => {
154
+ ensureTrapZoneHasFocus(event.target);
155
+ }, // use capture to ensure we get all events. focus events do not bubble
156
+ {
157
+ signal: wrappingController.signal,
158
+ capture: true
159
+ }); // focus the first element
160
+
161
+ ensureTrapZoneHasFocus(document.activeElement);
162
+ activeTrap = {
163
+ container,
164
+ controller: wrappingController,
165
+ initialFocus,
166
+ originalSignal: signal
167
+ }; // If we are activating a focus trap for a container that was previously
168
+ // suspended, just remove it from the suspended list.
169
+
170
+ const suspendedTrapIndex = suspendedTrapStack.findIndex(t => t.container === container);
171
+
172
+ if (suspendedTrapIndex >= 0) {
173
+ suspendedTrapStack.splice(suspendedTrapIndex, 1);
174
+ }
175
+
176
+ if (!abortSignal) {
177
+ return controller;
178
+ }
179
+ }