UNPKG

semantic-ui-react

Version:
202 lines (164 loc) 5.48 kB
import cx from 'clsx' import _ from 'lodash' import PropTypes from 'prop-types' import React from 'react' import { ModernAutoControlledComponent as Component, childrenUtils, customPropTypes, createShorthandFactory, getElementType, getUnhandledProps, SUI, useKeyOnly, useKeyOrValueAndKey, useValueAndKey, useWidthProp, } from '../../lib' import MenuHeader from './MenuHeader' import MenuItem from './MenuItem' import MenuMenu from './MenuMenu' /** * A menu displays grouped navigation actions. * @see Dropdown */ class Menu extends Component { handleItemOverrides = (predefinedProps) => ({ onClick: (e, itemProps) => { const { index } = itemProps this.setState({ activeIndex: index }) _.invoke(predefinedProps, 'onClick', e, itemProps) _.invoke(this.props, 'onItemClick', e, itemProps) }, }) renderItems() { const { items } = this.props const { activeIndex } = this.state return _.map(items, (item, index) => MenuItem.create(item, { defaultProps: { active: parseInt(activeIndex, 10) === index, index, }, overrideProps: this.handleItemOverrides, }), ) } render() { const { attached, borderless, children, className, color, compact, fixed, floated, fluid, icon, inverted, pagination, pointing, secondary, size, stackable, tabular, text, vertical, widths, } = this.props const classes = cx( 'ui', color, size, useKeyOnly(borderless, 'borderless'), useKeyOnly(compact, 'compact'), useKeyOnly(fluid, 'fluid'), useKeyOnly(inverted, 'inverted'), useKeyOnly(pagination, 'pagination'), useKeyOnly(pointing, 'pointing'), useKeyOnly(secondary, 'secondary'), useKeyOnly(stackable, 'stackable'), useKeyOnly(text, 'text'), useKeyOnly(vertical, 'vertical'), useKeyOrValueAndKey(attached, 'attached'), useKeyOrValueAndKey(floated, 'floated'), useKeyOrValueAndKey(icon, 'icon'), useKeyOrValueAndKey(tabular, 'tabular'), useValueAndKey(fixed, 'fixed'), useWidthProp(widths, 'item'), className, 'menu', ) const rest = getUnhandledProps(Menu, this.props) const ElementType = getElementType(Menu, this.props) return ( <ElementType {...rest} className={classes}> {childrenUtils.isNil(children) ? this.renderItems() : children} </ElementType> ) } } Menu.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, /** Index of the currently active item. */ activeIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), /** A menu may be attached to other content segments. */ attached: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['top', 'bottom'])]), /** A menu item or menu can have no borders. */ borderless: PropTypes.bool, /** Primary content. */ children: PropTypes.node, /** Additional classes. */ className: PropTypes.string, /** Additional colors can be specified. */ color: PropTypes.oneOf(SUI.COLORS), /** A menu can take up only the space necessary to fit its content. */ compact: PropTypes.bool, /** Initial activeIndex value. */ defaultActiveIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), /** A menu can be fixed to a side of its context. */ fixed: PropTypes.oneOf(['left', 'right', 'bottom', 'top']), /** A menu can be floated. */ floated: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['right'])]), /** A vertical menu may take the size of its container. */ fluid: PropTypes.bool, /** A menu may have just icons (bool) or labeled icons. */ icon: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['labeled'])]), /** A menu may have its colors inverted to show greater contrast. */ inverted: PropTypes.bool, /** Shorthand array of props for Menu. */ items: customPropTypes.collectionShorthand, /** * onClick handler for MenuItem. Mutually exclusive with children. * * @param {SyntheticEvent} event - React's original SyntheticEvent. * @param {object} data - All item props. */ onItemClick: customPropTypes.every([customPropTypes.disallow(['children']), PropTypes.func]), /** A pagination menu is specially formatted to present links to pages of content. */ pagination: PropTypes.bool, /** A menu can point to show its relationship to nearby content. */ pointing: PropTypes.bool, /** A menu can adjust its appearance to de-emphasize its contents. */ secondary: PropTypes.bool, /** A menu can vary in size. */ size: PropTypes.oneOf(_.without(SUI.SIZES, 'medium', 'big')), /** A menu can stack at mobile resolutions. */ stackable: PropTypes.bool, /** A menu can be formatted to show tabs of information. */ tabular: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['right'])]), /** A menu can be formatted for text content. */ text: PropTypes.bool, /** A vertical menu displays elements vertically. */ vertical: PropTypes.bool, /** A menu can have its items divided evenly. */ widths: PropTypes.oneOf(SUI.WIDTHS), } Menu.autoControlledProps = ['activeIndex'] Menu.Header = MenuHeader Menu.Item = MenuItem Menu.Menu = MenuMenu Menu.create = createShorthandFactory(Menu, (items) => ({ items })) export default Menu