UNPKG

@carbon/ibm-products

Version:
80 lines (78 loc) 3.17 kB
/** * 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;