@primer/components 0.0.0-20211030163410 → 0.0.0-20211030175556
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.
- package/CHANGELOG.md +2 -28
- package/dist/browser.esm.js +591 -602
- package/dist/browser.esm.js.map +1 -1
- package/dist/browser.umd.js +200 -211
- package/dist/browser.umd.js.map +1 -1
- package/lib/ActionList/Divider.jsx +29 -0
- package/lib/ActionList/Group.jsx +23 -0
- package/lib/ActionList/Header.jsx +66 -0
- package/lib/ActionList/Item.js +3 -3
- package/lib/ActionList/Item.jsx +288 -0
- package/lib/ActionList/List.jsx +138 -0
- package/lib/ActionList/index.js +12 -23
- package/lib/ActionList2/Description.jsx +29 -0
- package/lib/ActionList2/Divider.jsx +22 -0
- package/lib/ActionList2/Group.jsx +54 -0
- package/lib/ActionList2/Header.d.ts +26 -0
- package/lib/ActionList2/Header.js +55 -0
- package/lib/ActionList2/Header.jsx +36 -0
- package/lib/ActionList2/Item.js +1 -3
- package/lib/ActionList2/Item.jsx +174 -0
- package/lib/ActionList2/LinkItem.jsx +28 -0
- package/lib/ActionList2/List.js +2 -1
- package/lib/ActionList2/List.jsx +41 -0
- package/lib/ActionList2/Selection.js +1 -3
- package/lib/ActionList2/Selection.jsx +50 -0
- package/lib/ActionList2/Visuals.jsx +48 -0
- package/lib/ActionList2/index.js +23 -41
- package/lib/ActionMenu.jsx +73 -0
- package/lib/AnchoredOverlay/AnchoredOverlay.jsx +100 -0
- package/lib/AnchoredOverlay/index.js +4 -12
- package/lib/Autocomplete/Autocomplete.d.ts +0 -1
- package/lib/Autocomplete/Autocomplete.jsx +100 -0
- package/lib/Autocomplete/AutocompleteContext.jsx +5 -0
- package/lib/Autocomplete/AutocompleteInput.d.ts +0 -1
- package/lib/Autocomplete/AutocompleteInput.jsx +113 -0
- package/lib/Autocomplete/AutocompleteMenu.js +13 -6
- package/lib/Autocomplete/AutocompleteMenu.jsx +190 -0
- package/lib/Autocomplete/AutocompleteOverlay.jsx +55 -0
- package/lib/Autocomplete/index.js +7 -14
- package/lib/Avatar.jsx +34 -0
- package/lib/AvatarPair.jsx +29 -0
- package/lib/AvatarStack.jsx +151 -0
- package/lib/BaseStyles.jsx +65 -0
- package/lib/BorderBox.jsx +18 -0
- package/lib/Box.jsx +10 -0
- package/lib/BranchName.jsx +20 -0
- package/lib/Breadcrumbs.jsx +71 -0
- package/lib/Button/Button.d.ts +0 -1
- package/lib/Button/Button.jsx +40 -0
- package/lib/Button/ButtonBase.jsx +33 -0
- package/lib/Button/ButtonClose.d.ts +1 -2
- package/lib/Button/ButtonClose.jsx +53 -0
- package/lib/Button/ButtonDanger.d.ts +0 -1
- package/lib/Button/ButtonDanger.jsx +43 -0
- package/lib/Button/ButtonGroup.jsx +55 -0
- package/lib/Button/ButtonInvisible.d.ts +0 -1
- package/lib/Button/ButtonInvisible.jsx +32 -0
- package/lib/Button/ButtonOutline.d.ts +0 -1
- package/lib/Button/ButtonOutline.jsx +43 -0
- package/lib/Button/ButtonPrimary.d.ts +0 -1
- package/lib/Button/ButtonPrimary.jsx +42 -0
- package/lib/Button/ButtonStyles.jsx +37 -0
- package/lib/Button/ButtonTableList.jsx +46 -0
- package/lib/Button/index.js +21 -70
- package/lib/Caret.jsx +93 -0
- package/lib/CircleBadge.jsx +42 -0
- package/lib/CircleOcticon.d.ts +0 -1
- package/lib/CircleOcticon.jsx +21 -0
- package/lib/CounterLabel.jsx +43 -0
- package/lib/Details.jsx +21 -0
- package/lib/Dialog/ConfirmationDialog.jsx +146 -0
- package/lib/Dialog/Dialog.jsx +279 -0
- package/lib/Dialog.d.ts +2 -3
- package/lib/Dialog.jsx +129 -0
- package/lib/Dropdown.d.ts +0 -4
- package/lib/Dropdown.jsx +131 -0
- package/lib/DropdownMenu/DropdownButton.d.ts +1 -2
- package/lib/DropdownMenu/DropdownButton.jsx +14 -0
- package/lib/DropdownMenu/DropdownMenu.jsx +70 -0
- package/lib/DropdownMenu/index.js +6 -20
- package/lib/DropdownStyles.js +18 -26
- package/lib/FilterList.d.ts +0 -1
- package/lib/FilterList.jsx +59 -0
- package/lib/FilteredActionList/FilteredActionList.jsx +100 -0
- package/lib/FilteredActionList/index.js +4 -12
- package/lib/FilteredSearch.jsx +28 -0
- package/lib/Flash.jsx +69 -0
- package/lib/Flex.jsx +15 -0
- package/lib/FormGroup.jsx +22 -0
- package/lib/Grid.jsx +15 -0
- package/lib/Header.jsx +83 -0
- package/lib/Heading.jsx +21 -0
- package/lib/Label.jsx +82 -0
- package/lib/LabelGroup.jsx +18 -0
- package/lib/Link.jsx +36 -0
- package/lib/NewButton/button-counter.jsx +14 -0
- package/lib/NewButton/button.jsx +279 -0
- package/lib/NewButton/index.js +5 -12
- package/lib/NewButton/types.js +2 -1
- package/lib/Overlay.d.ts +3 -5
- package/lib/Overlay.jsx +154 -0
- package/lib/Pagehead.jsx +17 -0
- package/lib/Pagination/Pagination.jsx +161 -0
- package/lib/Pagination/index.js +6 -12
- package/lib/Pagination/model.jsx +174 -0
- package/lib/PointerBox.jsx +25 -0
- package/lib/Popover.jsx +202 -0
- package/lib/Portal/Portal.jsx +79 -0
- package/lib/Portal/index.js +5 -16
- package/lib/Position.d.ts +4 -4
- package/lib/Position.jsx +46 -0
- package/lib/ProgressBar.jsx +39 -0
- package/lib/SelectMenu/SelectMenu.d.ts +4 -10
- package/lib/SelectMenu/SelectMenu.jsx +112 -0
- package/lib/SelectMenu/SelectMenuContext.jsx +5 -0
- package/lib/SelectMenu/SelectMenuDivider.jsx +42 -0
- package/lib/SelectMenu/SelectMenuFilter.jsx +58 -0
- package/lib/SelectMenu/SelectMenuFooter.jsx +45 -0
- package/lib/SelectMenu/SelectMenuHeader.jsx +42 -0
- package/lib/SelectMenu/SelectMenuItem.d.ts +1 -1
- package/lib/SelectMenu/SelectMenuItem.jsx +142 -0
- package/lib/SelectMenu/SelectMenuList.jsx +59 -0
- package/lib/SelectMenu/SelectMenuLoadingAnimation.jsx +22 -0
- package/lib/SelectMenu/SelectMenuModal.d.ts +1 -1
- package/lib/SelectMenu/SelectMenuModal.jsx +118 -0
- package/lib/SelectMenu/SelectMenuTab.jsx +92 -0
- package/lib/SelectMenu/SelectMenuTabPanel.jsx +42 -0
- package/lib/SelectMenu/SelectMenuTabs.jsx +57 -0
- package/lib/SelectMenu/hooks/useKeyboardNav.js +80 -96
- package/lib/SelectMenu/index.js +7 -14
- package/lib/SelectPanel/SelectPanel.jsx +105 -0
- package/lib/SelectPanel/index.js +4 -12
- package/lib/SideNav.jsx +173 -0
- package/lib/Spinner.jsx +35 -0
- package/lib/StateLabel.jsx +93 -0
- package/lib/StyledOcticon.jsx +18 -0
- package/lib/SubNav.jsx +101 -0
- package/lib/TabNav.jsx +58 -0
- package/lib/Text.jsx +14 -0
- package/lib/TextInput.jsx +23 -0
- package/lib/TextInputWithTokens.d.ts +0 -1
- package/lib/TextInputWithTokens.jsx +218 -0
- package/lib/ThemeProvider.jsx +130 -0
- package/lib/Timeline.jsx +123 -0
- package/lib/Token/AvatarToken.d.ts +1 -1
- package/lib/Token/AvatarToken.jsx +54 -0
- package/lib/Token/IssueLabelToken.d.ts +1 -1
- package/lib/Token/IssueLabelToken.jsx +125 -0
- package/lib/Token/Token.d.ts +1 -1
- package/lib/Token/Token.jsx +103 -0
- package/lib/Token/TokenBase.jsx +88 -0
- package/lib/Token/_RemoveTokenButton.jsx +108 -0
- package/lib/Token/_TokenTextContainer.jsx +49 -0
- package/lib/Token/index.js +11 -30
- package/lib/Tooltip.jsx +246 -0
- package/lib/Truncate.jsx +24 -0
- package/lib/UnderlineNav.jsx +88 -0
- package/lib/_TextInputWrapper.jsx +120 -0
- package/lib/_UnstyledTextInput.jsx +22 -0
- package/lib/behaviors/anchoredPosition.js +205 -234
- package/lib/behaviors/focusTrap.js +121 -157
- package/lib/behaviors/focusZone.js +434 -509
- package/lib/behaviors/scrollIntoViewingArea.js +18 -35
- package/lib/constants.js +39 -43
- package/lib/drafts.js +20 -30
- package/lib/hooks/index.js +16 -60
- package/lib/hooks/useAnchoredPosition.js +32 -40
- package/lib/hooks/useCombinedRefs.js +32 -36
- package/lib/hooks/useDetails.jsx +39 -0
- package/lib/hooks/useDialog.js +72 -96
- package/lib/hooks/useFocusTrap.js +43 -60
- package/lib/hooks/useFocusZone.js +54 -50
- package/lib/hooks/useOnEscapePress.js +25 -36
- package/lib/hooks/useOnOutsideClick.jsx +61 -0
- package/lib/hooks/useOpenAndCloseFocus.js +22 -34
- package/lib/hooks/useOverlay.jsx +15 -0
- package/lib/hooks/useProvidedRefOrCreate.js +10 -14
- package/lib/hooks/useProvidedStateOrCreate.js +13 -16
- package/lib/hooks/useRenderForcingRef.js +13 -17
- package/lib/hooks/useResizeObserver.js +15 -18
- package/lib/hooks/useSafeTimeout.js +22 -30
- package/lib/hooks/useScrollFlash.js +16 -23
- package/lib/index.d.ts +0 -5
- package/lib/index.js +163 -676
- package/lib/polyfills/eventListenerSignal.js +37 -45
- package/lib/sx.js +10 -22
- package/lib/theme-preval.js +64 -3169
- package/lib/theme.js +3 -12
- package/lib/utils/create-slots.jsx +65 -0
- package/lib/utils/deprecate.jsx +59 -0
- package/lib/utils/isNumeric.jsx +7 -0
- package/lib/utils/iterateFocusableElements.js +63 -85
- package/lib/utils/ssr.jsx +6 -0
- package/lib/utils/test-deprecations.jsx +20 -0
- package/lib/utils/test-helpers.jsx +8 -0
- package/lib/utils/test-matchers.jsx +100 -0
- package/lib/utils/testing.d.ts +1 -2
- package/lib/utils/testing.js +0 -29
- package/lib/utils/testing.jsx +206 -0
- package/lib/utils/theme.js +33 -47
- package/lib/utils/types/AriaRole.js +2 -1
- package/lib/utils/types/ComponentProps.js +2 -1
- package/lib/utils/types/Flatten.js +2 -1
- package/lib/utils/types/KeyPaths.js +2 -1
- package/lib/utils/types/MandateProps.js +16 -1
- package/lib/utils/types/Merge.js +2 -1
- package/lib/utils/types/index.js +16 -69
- package/lib/utils/uniqueId.js +5 -8
- package/lib/utils/use-force-update.js +8 -14
- package/lib/utils/useIsomorphicLayoutEffect.js +8 -11
- package/lib/utils/userAgent.js +8 -12
- package/lib-esm/ActionList/Item.js +3 -3
- package/lib-esm/ActionList2/Header.d.ts +26 -0
- package/lib-esm/ActionList2/Header.js +44 -0
- package/lib-esm/ActionList2/Item.js +1 -3
- package/lib-esm/ActionList2/List.js +2 -1
- package/lib-esm/ActionList2/Selection.js +1 -3
- package/lib-esm/Autocomplete/Autocomplete.d.ts +0 -1
- package/lib-esm/Autocomplete/AutocompleteInput.d.ts +0 -1
- package/lib-esm/Autocomplete/AutocompleteMenu.js +13 -3
- package/lib-esm/Button/Button.d.ts +0 -1
- package/lib-esm/Button/ButtonClose.d.ts +1 -2
- package/lib-esm/Button/ButtonDanger.d.ts +0 -1
- package/lib-esm/Button/ButtonInvisible.d.ts +0 -1
- package/lib-esm/Button/ButtonOutline.d.ts +0 -1
- package/lib-esm/Button/ButtonPrimary.d.ts +0 -1
- package/lib-esm/CircleOcticon.d.ts +0 -1
- package/lib-esm/Dialog.d.ts +2 -3
- package/lib-esm/Dropdown.d.ts +0 -4
- package/lib-esm/DropdownMenu/DropdownButton.d.ts +1 -2
- package/lib-esm/FilterList.d.ts +0 -1
- package/lib-esm/Overlay.d.ts +3 -5
- package/lib-esm/Position.d.ts +4 -4
- package/lib-esm/SelectMenu/SelectMenu.d.ts +4 -10
- package/lib-esm/SelectMenu/SelectMenuItem.d.ts +1 -1
- package/lib-esm/SelectMenu/SelectMenuModal.d.ts +1 -1
- package/lib-esm/TextInputWithTokens.d.ts +0 -1
- package/lib-esm/Token/AvatarToken.d.ts +1 -1
- package/lib-esm/Token/IssueLabelToken.d.ts +1 -1
- package/lib-esm/Token/Token.d.ts +1 -1
- package/lib-esm/index.d.ts +0 -5
- package/lib-esm/index.js +0 -4
- package/lib-esm/theme-preval.js +0 -446
- package/lib-esm/utils/testing.d.ts +1 -2
- package/lib-esm/utils/testing.js +0 -24
- package/package.json +6 -5
- package/lib/Checkbox.d.ts +0 -29
- package/lib/Checkbox.js +0 -64
- package/lib/CheckboxInputField.d.ts +0 -11
- package/lib/CheckboxInputField.js +0 -74
- package/lib/RadioInputField.d.ts +0 -9
- package/lib/RadioInputField.js +0 -83
- package/lib/TextInputField.d.ts +0 -581
- package/lib/TextInputField.js +0 -66
- package/lib/_InputCaption.d.ts +0 -6
- package/lib/_InputCaption.js +0 -23
- package/lib/_InputField/InputField.d.ts +0 -39
- package/lib/_InputField/InputField.js +0 -90
- package/lib/_InputField/InputFieldCaption.d.ts +0 -3
- package/lib/_InputField/InputFieldCaption.js +0 -28
- package/lib/_InputField/InputFieldLabel.d.ts +0 -9
- package/lib/_InputField/InputFieldLabel.js +0 -34
- package/lib/_InputField/InputFieldValidation.d.ts +0 -6
- package/lib/_InputField/InputFieldValidation.js +0 -17
- package/lib/_InputField/ToggleInputField.d.ts +0 -13
- package/lib/_InputField/ToggleInputField.js +0 -71
- package/lib/_InputField/ToggleInputLeadingVisual.d.ts +0 -3
- package/lib/_InputField/ToggleInputLeadingVisual.js +0 -22
- package/lib/_InputField/ValidationAnimationContainer.d.ts +0 -6
- package/lib/_InputField/ValidationAnimationContainer.js +0 -48
- package/lib/_InputField/index.d.ts +0 -1
- package/lib/_InputField/index.js +0 -15
- package/lib/_InputField/slots.d.ts +0 -13
- package/lib/_InputField/slots.js +0 -17
- package/lib/_InputLabel.d.ts +0 -8
- package/lib/_InputLabel.js +0 -44
- package/lib/_InputValidation.d.ts +0 -8
- package/lib/_InputValidation.js +0 -56
- package/lib/_VisuallyHidden.d.ts +0 -6
- package/lib/_VisuallyHidden.js +0 -39
- package/lib/utils/types/FormValidationStatus.d.ts +0 -1
- package/lib/utils/types/FormValidationStatus.js +0 -1
- package/lib-esm/Checkbox.d.ts +0 -29
- package/lib-esm/Checkbox.js +0 -44
- package/lib-esm/CheckboxInputField.d.ts +0 -11
- package/lib-esm/CheckboxInputField.js +0 -57
- package/lib-esm/RadioInputField.d.ts +0 -9
- package/lib-esm/RadioInputField.js +0 -66
- package/lib-esm/TextInputField.d.ts +0 -581
- package/lib-esm/TextInputField.js +0 -50
- package/lib-esm/_InputCaption.d.ts +0 -6
- package/lib-esm/_InputCaption.js +0 -12
- package/lib-esm/_InputField/InputField.d.ts +0 -39
- package/lib-esm/_InputField/InputField.js +0 -70
- package/lib-esm/_InputField/InputFieldCaption.d.ts +0 -3
- package/lib-esm/_InputField/InputFieldCaption.js +0 -16
- package/lib-esm/_InputField/InputFieldLabel.d.ts +0 -9
- package/lib-esm/_InputField/InputFieldLabel.js +0 -22
- package/lib-esm/_InputField/InputFieldValidation.d.ts +0 -6
- package/lib-esm/_InputField/InputFieldValidation.js +0 -7
- package/lib-esm/_InputField/ToggleInputField.d.ts +0 -13
- package/lib-esm/_InputField/ToggleInputField.js +0 -54
- package/lib-esm/_InputField/ToggleInputLeadingVisual.d.ts +0 -3
- package/lib-esm/_InputField/ToggleInputLeadingVisual.js +0 -11
- package/lib-esm/_InputField/ValidationAnimationContainer.d.ts +0 -6
- package/lib-esm/_InputField/ValidationAnimationContainer.js +0 -33
- package/lib-esm/_InputField/index.d.ts +0 -1
- package/lib-esm/_InputField/index.js +0 -1
- package/lib-esm/_InputField/slots.d.ts +0 -13
- package/lib-esm/_InputField/slots.js +0 -5
- package/lib-esm/_InputLabel.d.ts +0 -8
- package/lib-esm/_InputLabel.js +0 -32
- package/lib-esm/_InputValidation.d.ts +0 -8
- package/lib-esm/_InputValidation.js +0 -43
- package/lib-esm/_VisuallyHidden.d.ts +0 -6
- package/lib-esm/_VisuallyHidden.js +0 -26
- package/lib-esm/utils/types/FormValidationStatus.d.ts +0 -1
- package/lib-esm/utils/types/FormValidationStatus.js +0 -1
@@ -1,34 +1,25 @@
|
|
1
1
|
"use strict";
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
var _iterateFocusableElements = require("../utils/iterateFocusableElements");
|
9
|
-
|
10
|
-
var _eventListenerSignal = require("../polyfills/eventListenerSignal");
|
11
|
-
|
12
|
-
(0, _eventListenerSignal.polyfill)();
|
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();
|
13
7
|
const suspendedTrapStack = [];
|
14
8
|
let activeTrap = undefined;
|
15
|
-
|
16
9
|
function tryReactivate() {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
23
16
|
// could replace this function. @see https://github.com/whatwg/dom/issues/920
|
24
|
-
|
25
|
-
|
26
17
|
function followSignal(signal) {
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
18
|
+
const controller = new AbortController();
|
19
|
+
signal.addEventListener('abort', () => {
|
20
|
+
controller.abort();
|
21
|
+
});
|
22
|
+
return controller;
|
32
23
|
}
|
33
24
|
/**
|
34
25
|
* Returns the first focusable child of `container`. If `lastChild` is true,
|
@@ -36,144 +27,117 @@ function followSignal(signal) {
|
|
36
27
|
* @param container
|
37
28
|
* @param lastChild
|
38
29
|
*/
|
39
|
-
|
40
|
-
|
41
30
|
function getFocusableChild(container, lastChild = false) {
|
42
|
-
|
43
|
-
reverse: lastChild,
|
44
|
-
strict: true,
|
45
|
-
onlyTabbable: true
|
46
|
-
}).next().value;
|
31
|
+
return iterateFocusableElements_1.iterateFocusableElements(container, { reverse: lastChild, strict: true, onlyTabbable: true }).next().value;
|
47
32
|
}
|
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
|
-
|
55
33
|
function focusTrap(container, initialFocus, abortSignal) {
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
+
}
|
102
81
|
}
|
103
|
-
}
|
104
82
|
}
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
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);
|
125
105
|
}
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
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.
|
144
135
|
const suspendedTrapIndex = suspendedTrapStack.findIndex(t => t.container === container);
|
145
|
-
|
146
136
|
if (suspendedTrapIndex >= 0) {
|
147
|
-
|
137
|
+
suspendedTrapStack.splice(suspendedTrapIndex, 1);
|
148
138
|
}
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
-
}
|
139
|
+
if (!abortSignal) {
|
140
|
+
return controller;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
exports.focusTrap = focusTrap;
|