@gravity-ui/uikit
Version:
Gravity UI base styling and components
101 lines (100 loc) • 3.87 kB
JavaScript
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
;