@shopify/polaris
Version:
Shopify’s product component library
77 lines (64 loc) • 2.8 kB
JavaScript
import { Key } from '../../types.js';
import React$1, { useState, useRef, useEffect } from 'react';
import { EventListener as EventListener$1 } from '../EventListener/EventListener.js';
import { useFocusManager } from '../../utilities/focus-manager/hooks.js';
import { focusFirstFocusableNode, findFirstKeyboardFocusableNode, findLastKeyboardFocusableNode, focusFirstKeyboardFocusableNode, focusLastKeyboardFocusableNode } from '../../utilities/focus.js';
import { KeypressListener as KeypressListener$1 } from '../KeypressListener/KeypressListener.js';
import { Focus as Focus$1 } from '../Focus/Focus.js';
function TrapFocus({
trapping = true,
children
}) {
var [shouldFocusSelf, setFocusSelf] = useState(undefined);
var {
canSafelyFocus
} = useFocusManager();
var focusTrapWrapper = useRef(null);
useEffect(() => {
setFocusSelf(!(canSafelyFocus && focusTrapWrapper.current && focusTrapWrapper.current.contains(document.activeElement)));
}, [canSafelyFocus]);
var shouldDisableFirstElementFocus = () => {
if (shouldFocusSelf === undefined || !canSafelyFocus) {
return true;
}
return shouldFocusSelf ? !trapping : !shouldFocusSelf;
};
var handleFocusIn = event => {
var containerContentsHaveFocus = focusTrapWrapper.current && focusTrapWrapper.current.contains(document.activeElement);
if (trapping === false || !focusTrapWrapper.current || containerContentsHaveFocus) {
return;
}
if (canSafelyFocus && event.target instanceof HTMLElement && focusTrapWrapper.current !== event.target && !focusTrapWrapper.current.contains(event.target)) {
focusFirstFocusableNode(focusTrapWrapper.current);
}
};
var handleTab = event => {
if (trapping === false || !focusTrapWrapper.current) {
return;
}
var firstFocusableNode = findFirstKeyboardFocusableNode(focusTrapWrapper.current);
var lastFocusableNode = findLastKeyboardFocusableNode(focusTrapWrapper.current);
if (event.target === lastFocusableNode && !event.shiftKey) {
event.preventDefault();
focusFirstKeyboardFocusableNode(focusTrapWrapper.current);
}
if (event.target === firstFocusableNode && event.shiftKey) {
event.preventDefault();
focusLastKeyboardFocusableNode(focusTrapWrapper.current);
}
};
return /*#__PURE__*/React$1.createElement(Focus$1, {
disabled: shouldDisableFirstElementFocus(),
root: focusTrapWrapper.current
}, /*#__PURE__*/React$1.createElement("div", {
ref: focusTrapWrapper
}, /*#__PURE__*/React$1.createElement(EventListener$1, {
event: "focusin",
handler: handleFocusIn
}), /*#__PURE__*/React$1.createElement(KeypressListener$1, {
keyCode: Key.Tab,
keyEvent: "keydown",
handler: handleTab
}), children));
}
export { TrapFocus };