You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
3.0 KiB

const _excluded = ["as", "active", "eventKey"];
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
import * as React from 'react';
import { useContext } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';
import NavContext from './NavContext';
import SelectableContext, { makeEventKey } from './SelectableContext';
import Button from './Button';
import { dataAttr } from './DataKey';
import TabContext from './TabContext';
import { jsx as _jsx } from "react/jsx-runtime";
export function useNavItem({
key,
onClick,
active,
id,
role,
disabled
}) {
const parentOnSelect = useContext(SelectableContext);
const navContext = useContext(NavContext);
const tabContext = useContext(TabContext);
let isActive = active;
const props = {
role
};
if (navContext) {
if (!role && navContext.role === 'tablist') props.role = 'tab';
const contextControllerId = navContext.getControllerId(key != null ? key : null);
const contextControlledId = navContext.getControlledId(key != null ? key : null); // @ts-ignore
props[dataAttr('event-key')] = key;
props.id = contextControllerId || id;
isActive = active == null && key != null ? navContext.activeKey === key : active;
/**
* Simplified scenario for `mountOnEnter`.
*
* While it would make sense to keep 'aria-controls' for tabs that have been mounted at least
* once, it would also complicate the code quite a bit, for very little gain.
* The following implementation is probably good enough.
*
* @see https://github.com/react-restart/ui/pull/40#issuecomment-1009971561
*/
if (isActive || !(tabContext != null && tabContext.unmountOnExit) && !(tabContext != null && tabContext.mountOnEnter)) props['aria-controls'] = contextControlledId;
}
if (props.role === 'tab') {
props['aria-selected'] = isActive;
if (!isActive) {
props.tabIndex = -1;
}
if (disabled) {
props.tabIndex = -1;
props['aria-disabled'] = true;
}
}
props.onClick = useEventCallback(e => {
if (disabled) return;
onClick == null ? void 0 : onClick(e);
if (key == null) {
return;
}
if (parentOnSelect && !e.isPropagationStopped()) {
parentOnSelect(key, e);
}
});
return [props, {
isActive
}];
}
const NavItem = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
as: Component = Button,
active,
eventKey
} = _ref,
options = _objectWithoutPropertiesLoose(_ref, _excluded);
const [props, meta] = useNavItem(Object.assign({
key: makeEventKey(eventKey, options.href),
active
}, options)); // @ts-ignore
props[dataAttr('active')] = meta.isActive;
return /*#__PURE__*/_jsx(Component, Object.assign({}, options, props, {
ref: ref
}));
});
NavItem.displayName = 'NavItem';
export default NavItem;