@yandex/ui
Version:
Yandex UI components
75 lines (74 loc) • 4.29 kB
JavaScript
import { __assign, __rest } from "tslib";
import React, { useCallback, createRef, useMemo } from 'react';
import { cn } from '@bem-react/classname';
import { isKeyCode, Keys } from '../lib/keyboard';
import { TabsMenuTab } from './Tab/TabsMenu-Tab';
import './TabsMenu.css';
export var cnTabsMenu = cn('TabsMenu');
/**
* Компонент для создания горизонтального меню.
* @param {ITabsMenuProps} props
*/
export var TabsMenu = function (_a) {
var activeTab = _a.activeTab, onChange = _a.onChange, className = _a.className, innerRef = _a.innerRef, tabs = _a.tabs, addonAfter = _a.addonAfter, _b = _a.orientation, orientation = _b === void 0 ? 'vertical' : _b, externalTabsRefs = _a.tabsRefs,
// @ts-ignore
_theme = _a.theme,
// @ts-ignore
_layout = _a.layout, props = __rest(_a, ["activeTab", "onChange", "className", "innerRef", "tabs", "addonAfter", "orientation", "tabsRefs", "theme", "layout"]);
// eslint-disable-next-line react-hooks/rules-of-hooks
var tabsRefs = externalTabsRefs || useMemo(function () { return tabs.map(function () { return createRef(); }); }, [tabs]);
var onKeyDown = useCallback(function (event) {
if (isKeyCode(event.keyCode, [Keys.LEFT, Keys.DOWN, Keys.RIGHT, Keys.UP])) {
event.preventDefault();
var nextTabMenuIndex = 0;
var direction = isKeyCode(event.keyCode, [Keys.LEFT, Keys.UP]) ? -1 : 1;
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id === activeTab) {
nextTabMenuIndex = i;
break;
}
}
for (var i = nextTabMenuIndex; i < tabs.length; i += direction) {
nextTabMenuIndex += direction;
// При необходимости тут можно реализовать цикличный выбор табов,
// при попадании индекса за границу списка,
// выставлять nextTabMenuIndex в противоположное значение.
var isEdge = nextTabMenuIndex >= tabs.length || nextTabMenuIndex < 0;
var isTabNonDisabled = tabs[nextTabMenuIndex] && !tabs[nextTabMenuIndex].disabled;
if (isEdge || isTabNonDisabled) {
break;
}
}
var nextTabMenu = tabs[nextTabMenuIndex];
var nextTabMenuRef = tabsRefs[nextTabMenuIndex];
if (nextTabMenu !== undefined &&
nextTabMenuRef !== undefined &&
nextTabMenuRef.current !== null &&
(nextTabMenu.onClick !== undefined || onChange !== undefined)) {
nextTabMenuRef.current.focus();
// Не совем удачное решение, переключать табики через onClick,
// тут могут возникнуть проблемы с event, т.к. в этом кейсе это KeyboardEvent.
if (nextTabMenu.onClick !== undefined) {
nextTabMenu.onClick(event);
}
if (onChange !== undefined) {
onChange(nextTabMenuIndex.toString());
}
}
}
}, [activeTab, tabsRefs, tabs, onChange]);
return (React.createElement("ul", __assign({}, props, { "aria-orientation": orientation, className: cnTabsMenu(null, [className]), ref: innerRef, role: "tablist" }),
tabs.map(function (_a, index) {
var id = _a.id, disabled = _a.disabled, tabProps = __rest(_a, ["id", "disabled"]);
return (React.createElement(TabsMenuTab, __assign({}, tabProps, { innerRef: tabsRefs[index], first: index === 0, disabled: disabled, onClick: disabled || (!onChange && !tabProps.onClick) ? undefined : function (event) {
if (tabProps.onClick !== undefined) {
tabProps.onClick(event);
}
if (onChange !== undefined) {
onChange(id);
}
}, active: id === activeTab, key: id, onKeyDown: onKeyDown })));
}),
addonAfter));
};
TabsMenu.displayName = cnTabsMenu();