UNPKG

wix-style-react

Version:
145 lines 7.74 kB
import React from 'react'; import PropTypes from 'prop-types'; import IconButton from '../IconButton'; import { avatarShapes, dataHooks } from './constants'; import { WixStyleReactContext } from '../WixStyleReactProvider/context'; import Loader from '../Loader'; import { placeholderSVGs } from './assets'; import { st, classes } from './Avatar.st.css'; import { capitalize } from '../utils/cssClassUtils'; import stringToColor from './string-to-color'; import AvatarCore from './AvatarCore'; const getSizeNumber = size => Number(size.substring(4)); const defaultSize = 48; const minSmallIconButton = 60; /** * Avatar is a type of element that visually represents a user, either as an image, name initials or placeholder icon. */ class Avatar extends React.PureComponent { constructor(props) { super(props); this._onMouseEnter = () => { if (this.props.showIndicationOnHover) { this.setState({ showIndication: true }); } }; this._onMouseLeave = () => { if (this.props.showIndicationOnHover) { this.setState({ fadeIndication: true }); setTimeout(() => this.setState({ fadeIndication: false, showIndication: false }), 150); } }; this.state = { fadeIndication: false, showIndication: false, }; } render() { const { size, presence, indication, color, customIndication, onIndicationClick, dataHook, className, shape, text, placeholder, name, onClick, showIndicationOnHover, loading, ...rest } = this.props; const { fadeIndication, showIndication } = this.state; const calculatedColor = color || stringToColor(text || name); // if color is provided as a prop use it, otherwise, generate a color based on the text const sizeNumber = getSizeNumber(size); const renderOnHover = !showIndicationOnHover || showIndication; const indicationConstraints = renderOnHover && sizeNumber >= defaultSize; const renderIndication = indicationConstraints && !customIndication && indication; const renderCustomIndication = indicationConstraints && customIndication; const renderLoader = loading && sizeNumber >= defaultSize; return (React.createElement(WixStyleReactContext.Consumer, null, ({ newColorsBranding }) => (React.createElement("div", { "data-hook": dataHook, className: st(className, classes.root) }, React.createElement("div", { "data-hook": dataHooks.avatarWSR, onMouseEnter: this._onMouseEnter, onMouseLeave: this._onMouseLeave, className: st(classes.avatarContainer, { shape, size, indication: Boolean(customIndication || indication), presence: Boolean(presence), presenceType: presence, clickable: !!onClick, fade: fadeIndication, hasText: !!text, newColorsBranding, }) }, React.createElement("div", { className: classes.coreAvatar }, React.createElement(AvatarCore, { ...rest, placeholder: placeholder ?? (React.createElement(AvatarDefaultPlaceholder, { shape: shape, size: size })), text: text, name: name, onClick: onClick, initialsLimit: sizeNumber < 30 ? 1 : undefined, "data-hook": dataHooks.avatarCore, className: st(classes.avatar, classes[`color${capitalize(calculatedColor)}`]) })), renderLoader && [ React.createElement("div", { key: "overlay", className: st(classes.loaderContainer, classes.overlay) }), React.createElement("div", { key: "loader", className: st(classes.loaderContainer, classes.loader) }, React.createElement(Loader, { dataHook: dataHooks.loader, size: "tiny" })), ], presence && React.createElement("div", { className: classes.presence }), renderIndication && (React.createElement("div", { className: classes.indication }, React.createElement(IconButton, { className: classes.iconButtonShadow, dataHook: dataHooks.indication, onClick: onIndicationClick, skin: "inverted", shape: shape, size: sizeNumber > minSmallIconButton ? 'small' : 'tiny' }, indication))), renderCustomIndication && (React.createElement("div", { className: classes.indication, "data-hook": dataHooks.customIndication, onClick: onIndicationClick }, customIndication))))))); } } const AvatarDefaultPlaceholder = ({ shape, size }) => shape !== avatarShapes.square ? placeholderSVGs[size][avatarShapes.circle] : placeholderSVGs[size][avatarShapes.square]; const CoreAvatarPropTypes = { /** * Defines a name of the avatar user. Text initials will be generated from the name. * The name value will be used as default value for HTML title and `aria-label` attributes. * And also as default value for the image's alt attribute if `imgProps` is provided. */ name: PropTypes.string, /** Defines a text to render as a content instead of a given `name`. */ text: PropTypes.string, /** * Accept any content to render as a content placeholder. This placeholder will be displayed if no text, name or imgProps are provided.<br> * By default use a generic avatar user icon. */ placeholder: PropTypes.node, /** Accept all common `<img>` tag properties. */ imgProps: PropTypes.object, /** Defines a string that labels the current element in case where text label is not visible on the screen. */ ariaLabel: PropTypes.string, /** Defines a standard HTML title attribute value. Applies it to the root element. */ title: PropTypes.string, /** Defines a click event handler. When defined, component will be clickable and will have a pointer cursor on hover. */ onClick: PropTypes.func, }; Avatar.displayName = 'Avatar'; Avatar.propTypes = { ...CoreAvatarPropTypes, /** Controls the size of an avatar. */ size: PropTypes.oneOf([ 'size90', 'size72', 'size60', 'size48', 'size36', 'size30', 'size24', 'size18', ]), /** * Controls the background color of the avatar. If not provided, * color is determined by the provided text or name so that each name will receive a different color. */ color: PropTypes.oneOf(['A1', 'A2', 'A3', 'A4', 'A5', 'A6']), /** Controls the shape of the image. */ shape: PropTypes.oneOf(['circle', 'square']), /** Specifies a CSS class name to be appended to the component’s root element. */ className: PropTypes.string, /** Applies a data-hook HTML attribute that can be used in the tests. */ dataHook: PropTypes.string, /** Sets the presence status of an avatar. */ presence: PropTypes.oneOf(['online', 'offline', 'busy']), /** Accept any content to render as an indication item. */ indication: PropTypes.node, /** * Accept any content to render as a custom indication item. This indication element will not be wrapped by an IconButton. * It could be rendered in other shapes (such as square). * */ customIndication: PropTypes.node, /** Defines a callback function which is called every time indication element is clicked. */ onIndicationClick: PropTypes.func, /** Shows indication element on hover. */ showIndicationOnHover: PropTypes.bool, /** Shows a loader on top of an avatar. */ loading: PropTypes.bool, }; Avatar.defaultProps = { size: 'size48', shape: 'circle', showIndicationOnHover: false, }; export default Avatar; //# sourceMappingURL=Avatar.js.map