@wix/design-system
Version:
@wix/design-system
100 lines (99 loc) • 3.78 kB
JavaScript
;
exports.__esModule = true;
exports.useTabNavigation = useTabNavigation;
var _react = require("react");
function useTabNavigation() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var tabRefs = (0, _react.useRef)([]);
var containerRef = (0, _react.useRef)(null);
var getSelectedTabIndex = () => {
var _tabRefs$current;
return (_tabRefs$current = tabRefs.current) == null ? void 0 : _tabRefs$current.findIndex(el => el.getAttribute('aria-selected') === 'true');
};
var setFocusableTab = index => {
var _tabRefs$current2;
if ((_tabRefs$current2 = tabRefs.current) != null && _tabRefs$current2[index]) {
tabRefs.current.forEach((el, _index) => {
el.tabIndex = _index === index ? 0 : -1;
});
}
};
var handleKeyDown = (0, _react.useCallback)(e => {
var target = e.target;
var currentIndex = tabRefs.current.indexOf(target);
if (currentIndex === -1) return;
var orientation = options.orientation || 'horizontal';
var nextIndex = currentIndex;
var totalTabs = tabRefs.current.length;
switch (e.key) {
case 'ArrowRight':
if (orientation === 'horizontal') {
nextIndex = (currentIndex + 1) % totalTabs;
}
break;
case 'ArrowLeft':
if (orientation === 'horizontal') {
nextIndex = (currentIndex - 1 + totalTabs) % totalTabs;
}
break;
case 'ArrowDown':
if (orientation === 'vertical') {
nextIndex = (currentIndex + 1) % totalTabs;
}
break;
case 'ArrowUp':
if (orientation === 'vertical') {
nextIndex = (currentIndex - 1 + totalTabs) % totalTabs;
}
break;
case 'Home':
nextIndex = 0;
break;
case 'End':
nextIndex = totalTabs - 1;
break;
default:
return;
}
if (nextIndex !== currentIndex && tabRefs.current[nextIndex]) {
setFocusableTab(nextIndex);
tabRefs.current[nextIndex].focus();
e.preventDefault();
}
}, [options.orientation]);
var handleFocusOut = (0, _react.useCallback)(e => {
var _containerRef$current;
var relatedTarget = e.relatedTarget;
if (relatedTarget && (_containerRef$current = containerRef.current) != null && _containerRef$current.contains(relatedTarget)) {
return; // Focus is still within the container, don't adjust
}
var selectedTabIndex = getSelectedTabIndex();
setFocusableTab(selectedTabIndex !== -1 ? selectedTabIndex : 0);
}, []);
var setupTabs = (0, _react.useCallback)(() => {
if (!(containerRef != null && containerRef.current)) return;
containerRef.current.removeEventListener('keydown', handleKeyDown);
containerRef.current.removeEventListener('focusout', handleFocusOut);
var elements = containerRef.current.querySelectorAll('[role="tab"]');
tabRefs.current = Array.from(elements);
var selectedTabIndex = getSelectedTabIndex();
var focusedTabIndex = selectedTabIndex !== -1 ? selectedTabIndex : 0;
tabRefs.current.forEach((el, index) => {
el.tabIndex = index === focusedTabIndex ? 0 : -1;
});
containerRef.current.addEventListener('keydown', handleKeyDown);
containerRef.current.addEventListener('focusout', handleFocusOut);
}, [handleKeyDown, handleFocusOut]);
(0, _react.useEffect)(() => {
setupTabs();
var currentContainer = containerRef.current;
return () => {
if (currentContainer) {
currentContainer.removeEventListener('keydown', handleKeyDown);
currentContainer.removeEventListener('focusout', handleFocusOut);
}
};
}, [handleKeyDown, handleFocusOut, setupTabs]);
return containerRef;
}
//# sourceMappingURL=useTabNavigation.js.map