semantic-ui-react
Version:
The official Semantic-UI-React integration.
217 lines (180 loc) • 5.7 kB
JavaScript
import cx from 'clsx'
import _ from 'lodash'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import {
childrenUtils,
createShorthandFactory,
customPropTypes,
getElementType,
getUnhandledProps,
SUI,
useKeyOnly,
useKeyOrValueAndKey,
useValueAndKey,
} from '../../lib'
import Icon from '../Icon/Icon'
import Image from '../Image/Image'
import LabelDetail from './LabelDetail'
import LabelGroup from './LabelGroup'
/**
* A label displays content classification.
*/
export default class Label extends Component {
handleClick = (e) => {
const { onClick } = this.props
if (onClick) onClick(e, this.props)
}
handleIconOverrides = (predefinedProps) => ({
onClick: (e) => {
_.invoke(predefinedProps, 'onClick', e)
_.invoke(this.props, 'onRemove', e, this.props)
},
})
render() {
const {
active,
attached,
basic,
children,
circular,
className,
color,
content,
corner,
detail,
empty,
floating,
horizontal,
icon,
image,
onRemove,
pointing,
prompt,
removeIcon,
ribbon,
size,
tag,
} = this.props
const pointingClass =
(pointing === true && 'pointing') ||
((pointing === 'left' || pointing === 'right') && `${pointing} pointing`) ||
((pointing === 'above' || pointing === 'below') && `pointing ${pointing}`)
const classes = cx(
'ui',
color,
pointingClass,
size,
useKeyOnly(active, 'active'),
useKeyOnly(basic, 'basic'),
useKeyOnly(circular, 'circular'),
useKeyOnly(empty, 'empty'),
useKeyOnly(floating, 'floating'),
useKeyOnly(horizontal, 'horizontal'),
useKeyOnly(image === true, 'image'),
useKeyOnly(prompt, 'prompt'),
useKeyOnly(tag, 'tag'),
useKeyOrValueAndKey(corner, 'corner'),
useKeyOrValueAndKey(ribbon, 'ribbon'),
useValueAndKey(attached, 'attached'),
'label',
className,
)
const rest = getUnhandledProps(Label, this.props)
const ElementType = getElementType(Label, this.props)
if (!childrenUtils.isNil(children)) {
return (
<ElementType {...rest} className={classes} onClick={this.handleClick}>
{children}
</ElementType>
)
}
const removeIconShorthand = _.isUndefined(removeIcon) ? 'delete' : removeIcon
return (
<ElementType className={classes} onClick={this.handleClick} {...rest}>
{Icon.create(icon, { autoGenerateKey: false })}
{typeof image !== 'boolean' && Image.create(image, { autoGenerateKey: false })}
{content}
{LabelDetail.create(detail, { autoGenerateKey: false })}
{onRemove &&
Icon.create(removeIconShorthand, {
autoGenerateKey: false,
overrideProps: this.handleIconOverrides,
})}
</ElementType>
)
}
}
Label.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
/** A label can be active. */
active: PropTypes.bool,
/** A label can attach to a content segment. */
attached: PropTypes.oneOf([
'top',
'bottom',
'top right',
'top left',
'bottom left',
'bottom right',
]),
/** A label can reduce its complexity. */
basic: PropTypes.bool,
/** Primary content. */
children: PropTypes.node,
/** A label can be circular. */
circular: PropTypes.bool,
/** Additional classes. */
className: PropTypes.string,
/** Color of the label. */
color: PropTypes.oneOf(SUI.COLORS),
/** Shorthand for primary content. */
content: customPropTypes.contentShorthand,
/** A label can position itself in the corner of an element. */
corner: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['left', 'right'])]),
/** Shorthand for LabelDetail. */
detail: customPropTypes.itemShorthand,
/** Formats the label as a dot. */
empty: customPropTypes.every([PropTypes.bool, customPropTypes.demand(['circular'])]),
/** Float above another element in the upper right corner. */
floating: PropTypes.bool,
/** A horizontal label is formatted to label content along-side it horizontally. */
horizontal: PropTypes.bool,
/** Shorthand for Icon. */
icon: customPropTypes.itemShorthand,
/** A label can be formatted to emphasize an image or prop can be used as shorthand for Image. */
image: PropTypes.oneOfType([PropTypes.bool, customPropTypes.itemShorthand]),
/**
* Called on click.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onClick: PropTypes.func,
/**
* Adds an "x" icon, called when "x" is clicked.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onRemove: PropTypes.func,
/** A label can point to content next to it. */
pointing: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOf(['above', 'below', 'left', 'right']),
]),
/** A label can prompt for an error in your forms. */
prompt: PropTypes.bool,
/** Shorthand for Icon to appear as the last child and trigger onRemove. */
removeIcon: customPropTypes.itemShorthand,
/** A label can appear as a ribbon attaching itself to an element. */
ribbon: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['right'])]),
/** A label can have different sizes. */
size: PropTypes.oneOf(SUI.SIZES),
/** A label can appear as a tag. */
tag: PropTypes.bool,
}
Label.Detail = LabelDetail
Label.Group = LabelGroup
Label.create = createShorthandFactory(Label, (value) => ({ content: value }))