import { Accessibility } from '@fluentui/accessibility'; import { ComponentWithAs, getElementType, useUnhandledProps, useAccessibility, useFluentContext, useStyles, useTelemetry, } from '@fluentui/react-bindings'; import * as customPropTypes from '@fluentui/react-proptypes'; import * as _ from 'lodash'; import * as PropTypes from 'prop-types'; import * as React from 'react'; import { childrenExist, createShorthandFactory, UIComponentProps, ChildrenComponentProps, ContentComponentProps, commonPropTypes, ColorComponentProps, rtlTextContainer, } from '../../utils'; import { Image, ImageProps } from '../Image/Image'; import { Box, BoxProps } from '../Box/Box'; import { ShorthandValue, FluentComponentStaticProps } from '../../types'; export interface LabelProps extends UIComponentProps, ChildrenComponentProps, ContentComponentProps>, ColorComponentProps { /** * Accessibility behavior if overridden by the user. */ accessibility?: Accessibility; /** A Label can be circular. */ circular?: boolean; /** A Label can take up the width of its container. */ fluid?: boolean; /** A Label can have an icon. */ icon?: ShorthandValue; /** A Label can position its Icon at the start or end of the layout. */ iconPosition?: 'start' | 'end'; /** A Label can contain an image. */ image?: ShorthandValue; /** A Label can position its image at the start or end of the layout. */ imagePosition?: 'start' | 'end'; } export type LabelStylesProps = Pick & { hasImage: boolean; hasIcon: boolean; hasActionableIcon: boolean; }; export const labelClassName = 'ui-label'; /** * A Label allows user to classify content. */ export const Label: ComponentWithAs<'span', LabelProps> & FluentComponentStaticProps = props => { const context = useFluentContext(); const { setStart, setEnd } = useTelemetry(Label.displayName, context.telemetry); setStart(); const { accessibility, children, className, circular, color, content, icon, iconPosition, design, styles, variables, image, imagePosition, } = props; const getA11Props = useAccessibility(accessibility, { debugName: Label.displayName, rtl: context.rtl, }); const { classes, styles: resolvedStyles } = useStyles(Label.displayName, { className: labelClassName, mapPropsToStyles: () => ({ hasActionableIcon: _.has(icon, 'onClick'), hasImage: !!image, hasIcon: !!icon, circular, color, imagePosition, iconPosition, }), mapPropsToInlineStyles: () => ({ className, design, styles, variables }), rtl: context.rtl, }); const ElementType = getElementType(props); const unhandledProps = useUnhandledProps(Label.handledProps, props); if (childrenExist(children)) { const element = ( {children} ); setEnd(); return element; } const imageElement = Image.create(image, { defaultProps: () => ({ styles: resolvedStyles.image, }), }); const iconElement = Box.create(icon, { defaultProps: () => ({ styles: resolvedStyles.icon, }), }); const contentElement = Box.create(content, { defaultProps: () => ({ styles: resolvedStyles.content, }), }); const startImage = imagePosition === 'start' && imageElement; const startIcon = iconPosition === 'start' && iconElement; const endIcon = iconPosition === 'end' && iconElement; const endImage = imagePosition === 'end' && imageElement; const element = ( {startImage} {startIcon} {contentElement} {endIcon} {endImage} ); setEnd(); return element; }; Label.displayName = 'Label'; Label.propTypes = { ...commonPropTypes.createCommon({ color: true, content: 'shorthand' }), circular: PropTypes.bool, icon: customPropTypes.shorthandAllowingChildren, iconPosition: PropTypes.oneOf(['start', 'end']), image: customPropTypes.itemShorthandWithoutJSX, imagePosition: PropTypes.oneOf(['start', 'end']), fluid: PropTypes.bool, }; Label.handledProps = Object.keys(Label.propTypes) as any; Label.defaultProps = { as: 'span', imagePosition: 'start', iconPosition: 'end', }; Label.create = createShorthandFactory({ Component: Label, mappedProp: 'content' });