@carbon/ibm-security
Version:
Carbon for Cloud & Cognitive IBM Security UI components
88 lines (81 loc) • 3.52 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
/**
* @file Helper methods for element focusing.
* @copyright IBM Security 2018 - 2021
*/
import React from 'react';
export var focusableElements = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]';
export var keyableElements = 'li:not([disabled])';
export var focusFirstElement = function focusFirstElement(element) {
var focusable = element.querySelector(focusableElements);
if (focusable) {
focusable.focus();
}
};
export var trapTabFocus = function trapTabFocus(element, event) {
var focusable = element.querySelectorAll(focusableElements);
if (focusable.length > 0) {
if (event.target === focusable[0] && event.shiftKey) {
event.preventDefault();
focusable[focusable.length - 1].focus();
} else if (event.target === focusable[focusable.length - 1] && !event.shiftKey) {
event.preventDefault();
focusable[0].focus();
}
}
};
/**
* Manage the focus and blur event of an element that contains multiple focusable elements. This
* hook is useful when you want to allow users to shift keyboard focus inside component and only
* apply blur effects when the keyboard focus has completely left this component.
*
* @param {number} [timeoutDelay=10] Millisecond delay for the blur effect to take place. This
* should not be less than 10 to give the browser time to register the subsequent focus event first.
*
* @returns {{createFocusHandler: Function, createBlurHandler: Function}} Utility functions to
* create the focus and blur handlers that apply the necessary effects or state changes.
*/
export var useComponentFocus = function useComponentFocus() {
var timeoutDelay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10;
var _React$useState = React.useState(undefined),
_React$useState2 = _slicedToArray(_React$useState, 2),
blurTimer = _React$useState2[0],
setBlurTimer = _React$useState2[1];
// Clear any timeouts before unmounting.
React.useEffect(function () {
return function () {
return clearTimeout(blurTimer);
};
}, [blurTimer]);
// Clears out the current timeout and sets the new one.
var setNewBlurTimer = function setNewBlurTimer(newTimeout) {
setBlurTimer(function (currentTimeout) {
clearTimeout(currentTimeout);
return newTimeout;
});
};
// Clear out any existing timer because this focus handler call indicates that the keyboard focus
// did not leave the component invoking this hook. Then apply the provided focus side effect.
var createFocusHandler = function createFocusHandler(callback) {
return function (event) {
setNewBlurTimer(undefined);
callback(event);
};
};
// Set a short delay to allow the browser to detect the subsequent focus event which should
// determine if the keyboard focus has completely left the component invoking this hook. If the
// timeout is allowed to execute, the provided side effect is applied.
var createBlurHandler = function createBlurHandler(callback) {
return function (event) {
var newTimeout = setTimeout(function () {
return callback(event);
}, timeoutDelay);
setNewBlurTimer(newTimeout);
};
};
// Return the two functions for the consumer to implement the necessary side effects.
return {
createFocusHandler: createFocusHandler,
createBlurHandler: createBlurHandler
};
};