UNPKG

@carbon/react

Version:

React components for the Carbon Design System

160 lines (156 loc) 4.94 kB
/** * Copyright IBM Corp. 2016, 2023 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js'; import cx from 'classnames'; import PropTypes from 'prop-types'; import React, { forwardRef } from 'react'; import { ArrowDown, ArrowUp } from '../../internal/keyboard/keys.js'; import { match } from '../../internal/keyboard/match.js'; import { usePrefix } from '../../internal/usePrefix.js'; import { warning } from '../../internal/warning.js'; import '../Text/index.js'; import { Text } from '../Text/Text.js'; const frFn = forwardRef; const OverflowMenuItem = frFn((props, ref) => { const { className, closeMenu, disabled = false, handleOverflowMenuItemFocus, hasDivider = false, href, isDelete = false, index, itemText = 'Provide itemText', onClick = () => {}, onKeyDown = () => {}, requireTitle, title, wrapperClassName, ...rest } = props; const prefix = usePrefix(); function setTabFocus(evt) { if (match(evt, ArrowDown)) { handleOverflowMenuItemFocus?.({ currentIndex: index, direction: 1 }); } if (match(evt, ArrowUp)) { handleOverflowMenuItemFocus?.({ currentIndex: index, direction: -1 }); } } function handleClick(evt) { onClick(evt); if (closeMenu) { closeMenu(); } } process.env.NODE_ENV !== "production" ? warning(!!closeMenu, '`<OverflowMenuItem>` detected missing `closeMenu` prop. ' + '`closeMenu` is required to let `<OverflowMenu>` close the menu upon actions on `<OverflowMenuItem>`. ' + 'Please make sure `<OverflowMenuItem>` is a direct child of `<OverflowMenu>.') : void 0; const overflowMenuBtnClasses = cx(`${prefix}--overflow-menu-options__btn`, className); const overflowMenuItemClasses = cx(`${prefix}--overflow-menu-options__option`, { [`${prefix}--overflow-menu--divider`]: hasDivider, [`${prefix}--overflow-menu-options__option--danger`]: isDelete, [`${prefix}--overflow-menu-options__option--disabled`]: disabled }, wrapperClassName); const TagToUse = href ? 'a' : 'button'; const OverflowMenuItemContent = (() => { if (typeof itemText !== 'string') { return itemText; } return /*#__PURE__*/React.createElement("div", { className: `${prefix}--overflow-menu-options__option-content` }, itemText); })(); return /*#__PURE__*/React.createElement(Text, { as: "li", className: overflowMenuItemClasses, role: "none" }, /*#__PURE__*/React.createElement(TagToUse, _extends({ className: overflowMenuBtnClasses, disabled: disabled, href: href, onClick: handleClick, onKeyDown: evt => { setTabFocus(evt); onKeyDown(evt); }, role: "menuitem" // ref as any: the type of `ref` is `ForwardedRef<HTMLButtonElement>` in `Button` component // but `OverflowMenuItem` can be rendered as `a` tag as well, which is `HTMLAnchorElement` // so we have to use `any` here , ref: ref, tabIndex: -1 // itemText as any: itemText may be a ReactNode, but `title` only accepts string // to avoid compatibility issue, we use `any` here. Consider to enforce `itemText` to be `string?` // in the next major release , title: requireTitle ? title || itemText : undefined }, rest), OverflowMenuItemContent)); }); OverflowMenuItem.propTypes = { /** * The CSS class name to be placed on the button element */ className: PropTypes.string, /** * A callback to tell the parent menu component that the menu should be closed. */ closeMenu: PropTypes.func, /** * `true` to make this menu item disabled. */ disabled: PropTypes.bool, handleOverflowMenuItemFocus: PropTypes.func, /** * `true` to make this menu item a divider. */ hasDivider: PropTypes.bool, /** * If given, overflow item will render as a link with the given href */ href: PropTypes.string, index: PropTypes.number, /** * `true` to make this menu item a "danger button". */ isDelete: PropTypes.bool, /** * The text in the menu item. */ itemText: PropTypes.node.isRequired, /** * event handlers */ onBlur: PropTypes.func, onClick: PropTypes.func, onFocus: PropTypes.func, onKeyDown: PropTypes.func, onKeyUp: PropTypes.func, onMouseDown: PropTypes.func, onMouseEnter: PropTypes.func, onMouseLeave: PropTypes.func, onMouseUp: PropTypes.func, /** * `true` if this menu item has long text and requires a browser tooltip */ requireTitle: PropTypes.bool, /** * Specify a title for the OverflowMenuItem */ title: PropTypes.string, /** * The CSS class name to be placed on the wrapper list item element */ wrapperClassName: PropTypes.string }; export { OverflowMenuItem as default };