UNPKG

semantic-ui-react

Version:
183 lines (159 loc) 4.88 kB
import cx from 'clsx' import _ from 'lodash' import PropTypes from 'prop-types' import React, { Component, isValidElement } from 'react' import { childrenUtils, createShorthandFactory, customPropTypes, getElementType, getUnhandledProps, useKeyOnly, } from '../../lib' import Image from '../Image' import ListContent from './ListContent' import ListDescription from './ListDescription' import ListHeader from './ListHeader' import ListIcon from './ListIcon' /** * A list item can contain a set of items. */ class ListItem extends Component { handleClick = (e) => { const { disabled } = this.props if (!disabled) _.invoke(this.props, 'onClick', e, this.props) } render() { const { active, children, className, content, description, disabled, header, icon, image, value, } = this.props const ElementType = getElementType(ListItem, this.props) const classes = cx( useKeyOnly(active, 'active'), useKeyOnly(disabled, 'disabled'), useKeyOnly(ElementType !== 'li', 'item'), className, ) const rest = getUnhandledProps(ListItem, this.props) const valueProp = ElementType === 'li' ? { value } : { 'data-value': value } if (!childrenUtils.isNil(children)) { return ( <ElementType {...valueProp} role='listitem' className={classes} onClick={this.handleClick} {...rest} > {children} </ElementType> ) } const iconElement = ListIcon.create(icon, { autoGenerateKey: false }) const imageElement = Image.create(image, { autoGenerateKey: false }) // See description of `content` prop for explanation about why this is necessary. if (!isValidElement(content) && _.isPlainObject(content)) { return ( <ElementType {...valueProp} role='listitem' className={classes} onClick={this.handleClick} {...rest} > {iconElement || imageElement} {ListContent.create(content, { autoGenerateKey: false, defaultProps: { header, description }, })} </ElementType> ) } const headerElement = ListHeader.create(header, { autoGenerateKey: false }) const descriptionElement = ListDescription.create(description, { autoGenerateKey: false }) if (iconElement || imageElement) { return ( <ElementType {...valueProp} role='listitem' className={classes} onClick={this.handleClick} {...rest} > {iconElement || imageElement} {(content || headerElement || descriptionElement) && ( <ListContent> {headerElement} {descriptionElement} {content} </ListContent> )} </ElementType> ) } return ( <ElementType {...valueProp} role='listitem' className={classes} onClick={this.handleClick} {...rest} > {headerElement} {descriptionElement} {content} </ElementType> ) } } ListItem.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, /** A list item can active. */ active: PropTypes.bool, /** Primary content. */ children: PropTypes.node, /** Additional classes. */ className: PropTypes.string, /** * Shorthand for primary content. * * Heads up! * * This is handled slightly differently than the typical `content` prop since * the wrapping ListContent is not used when there's no icon or image. * * If you pass content as: * - an element/literal, it's treated as the sibling node to * header/description (whether wrapped in Item.Content or not). * - a props object, it forces the presence of Item.Content and passes those * props to it. If you pass a content prop within that props object, it * will be treated as the sibling node to header/description. */ content: customPropTypes.itemShorthand, /** Shorthand for ListDescription. */ description: customPropTypes.itemShorthand, /** A list item can disabled. */ disabled: PropTypes.bool, /** Shorthand for ListHeader. */ header: customPropTypes.itemShorthand, /** Shorthand for ListIcon. */ icon: customPropTypes.every([customPropTypes.disallow(['image']), customPropTypes.itemShorthand]), /** Shorthand for Image. */ image: customPropTypes.every([customPropTypes.disallow(['icon']), customPropTypes.itemShorthand]), /** A ListItem can be clicked */ onClick: PropTypes.func, /** A value for an ordered list. */ value: PropTypes.string, } ListItem.create = createShorthandFactory(ListItem, (content) => ({ content })) export default ListItem