UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

101 lines (100 loc) 3.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTabList = useTabList; const tslib_1 = require("tslib"); const React = tslib_1.__importStar(require("react")); const constants_1 = require("../../../constants.js"); const theme_1 = require("../../theme/index.js"); const constants_2 = require("../constants.js"); const TabContext_1 = require("../contexts/TabContext.js"); const getAllTabElements = (tabElement) => { return [ ...(tabElement .closest('[role="tablist"]') ?.querySelectorAll(`[${constants_2.TAB_DATA_ATTRIBUTE}]`) ?? []), ]; }; const isTabDisabled = (tabElement) => { return Boolean(tabElement.getAttribute('aria-disabled')); }; const getTabValue = (tabElement) => { return tabElement.getAttribute(constants_2.TAB_DATA_ATTRIBUTE); }; const focusNearestTab = (event, isInverse, isRTL) => { const tabElement = event.target; const allTabElements = getAllTabElements(tabElement); const index = allTabElements.indexOf(tabElement); let distance = 1; while (distance < allTabElements.length) { const nextIndex = index + distance * (isRTL ? -1 : 1) * (isInverse ? -1 : 1); const nextTabElement = allTabElements.at(nextIndex % allTabElements.length); if (nextTabElement && !isTabDisabled(nextTabElement)) { nextTabElement.focus(); return nextTabElement; } distance++; } return tabElement; }; const focusFurthestTab = (event, isInverse) => { const tabElement = event.target; const allTabElements = getAllTabElements(tabElement); const stopIndex = isInverse ? 0 : allTabElements.length - 1; let index = allTabElements.indexOf(tabElement); let lastFocusableTabElement = tabElement; while (index !== stopIndex) { index += isInverse ? -1 : 1; const nextTabElement = allTabElements.at(index); if (nextTabElement && !isTabDisabled(nextTabElement)) { lastFocusableTabElement = nextTabElement; } } lastFocusableTabElement.focus(); return lastFocusableTabElement; }; function useTabList(tabListProps) { const tabContext = React.useContext(TabContext_1.TabContext); const isRTL = (0, theme_1.useDirection)() === 'rtl'; const activateOnFocus = (tabElement) => { const value = getTabValue(tabElement); if (tabListProps.activateOnFocus && value) { tabListProps.onUpdate?.(value); tabContext?.onUpdate?.(value); } }; const onKeyDown = (event) => { switch (event.code) { case constants_1.KeyCode.ARROW_LEFT: { event.preventDefault(); activateOnFocus(focusNearestTab(event, true, isRTL)); break; } case constants_1.KeyCode.ARROW_RIGHT: { event.preventDefault(); activateOnFocus(focusNearestTab(event, false, isRTL)); break; } case constants_1.KeyCode.HOME: { event.preventDefault(); activateOnFocus(focusFurthestTab(event, true)); break; } case constants_1.KeyCode.END: { event.preventDefault(); activateOnFocus(focusFurthestTab(event, false)); break; } } tabListProps.onKeyDown?.(event); }; const { value: _value, onUpdate: _onUpdate, size: _size, activateOnFocus: _activateOnFocus, qa: _qa, ...htmlProps } = tabListProps; return { ...htmlProps, role: 'tablist', 'aria-orientation': 'horizontal', onKeyDown, className: (0, constants_2.bTabList)({ size: tabListProps.size ?? 'm' }, tabListProps.className), 'data-qa': tabListProps.qa, }; } //# sourceMappingURL=useTabList.js.map