UNPKG

@wix/design-system

Version:

@wix/design-system

100 lines (99 loc) 3.78 kB
"use strict"; 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