@carbon/ibm-products
Version:
Carbon for IBM Products
80 lines (78 loc) • 3.17 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
require("../../../_virtual/_rolldown/runtime.js");
const require_settings = require("../../../settings.js");
let react = require("react");
let _carbon_react = require("@carbon/react");
//#region src/global/js/hooks/useFocus.js
/**
* Copyright IBM Corp. 2024, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
const getSpecificElement = (parentEl, elementId) => {
const element = parentEl?.querySelector(elementId);
return elementId && !element?.disabled ? element : null;
};
const useFocus = (modalRef, selectorPrimaryFocus) => {
const carbonPrefix = (0, _carbon_react.usePrefix)();
const tearsheetBaseClass = `${require_settings.pkg.prefix}--tearsheet`;
const sidePanelBaseClass = `${require_settings.pkg.prefix}--side-panel`;
const notQuery = `:not(.${carbonPrefix}--visually-hidden,.${tearsheetBaseClass}__header--no-close-icon,.${carbonPrefix}--btn--disabled,[aria-hidden="true"],[tabindex="-1"],[disabled])`;
const queryButton = `button${notQuery}`;
const queryInput = `input${notQuery}`;
const querySelect = `select${notQuery}`;
const queryTextarea = `textarea${notQuery}`;
const query = `${queryButton},${`[href]${notQuery}`},${`a${notQuery}`},${queryInput},${querySelect},${queryTextarea},${`[tabindex="0"]${notQuery}`},${`.${sidePanelBaseClass}--scrolls`}`;
const getFocusable = (0, react.useCallback)(() => {
let focusableElements = modalRef?.current?.querySelectorAll(`${query}`);
if (focusableElements?.length) focusableElements = Array.prototype.filter.call(focusableElements, (el) => window?.getComputedStyle(el)?.display !== "none");
return {
first: focusableElements?.[0],
last: focusableElements?.[focusableElements?.length - 1],
all: focusableElements,
specified: getSpecificElement(modalRef?.current, selectorPrimaryFocus)
};
}, [
modalRef,
query,
selectorPrimaryFocus
]);
(0, react.useEffect)(() => {
getFocusable();
}, [getFocusable, modalRef]);
const handleKeyDown = async (event) => {
if (event.key === "Tab") {
const { first, last } = getFocusable();
if (event.shiftKey && document?.activeElement === first) {
event.preventDefault();
last?.focus();
} else if (!event.shiftKey && document?.activeElement === last) {
event.preventDefault();
first?.focus();
}
}
};
const claimFocus = (0, react.useCallback)(() => {
const { first, specified } = getFocusable();
if (specified && window?.getComputedStyle(specified)?.display !== "none" && specified?.tabIndex !== -1) setTimeout(() => specified.focus(), 0);
else setTimeout(() => first?.focus(), 0);
}, [getFocusable]);
return {
firstElement: getFocusable()?.first,
lastElement: getFocusable()?.last,
allElements: getFocusable()?.all,
specifiedElement: getFocusable()?.specified,
keyDownListener: handleKeyDown,
getFocusable,
claimFocus
};
};
//#endregion
exports.getSpecificElement = getSpecificElement;
exports.useFocus = useFocus;