UNPKG

@hackplan/polaris

Version:

Shopify’s product component library

93 lines (92 loc) 3.6 kB
import React from 'react'; import { classNames, variationName } from '../../utilities/css'; import { isServer } from '../../utilities/target'; import { withAppProvider } from '../AppProvider'; import Image from '../Image'; import styles from './Avatar.scss'; import * as avatars from './images'; const STYLE_CLASSES = ['one', 'two', 'three', 'four', 'five', 'six']; const AVATAR_IMAGES = Object.keys(avatars).map( // import/namespace does not allow computed values by default // eslint-disable-next-line import/namespace (key) => avatars[key]); export class Avatar extends React.PureComponent { constructor() { super(...arguments); this.state = { hasError: false, hasLoaded: false, }; this.handleError = () => { this.setState({ hasError: true, hasLoaded: false }); }; this.handleLoad = () => { this.setState({ hasLoaded: true, hasError: false }); }; } static getDerivedStateFromProps(props, state) { if (props.source !== state.prevSource) { return { prevSource: props.source, hasError: false, hasLoaded: false, }; } return null; } render() { const { name, source, initials, customer, size = 'medium', accessibilityLabel, polaris: { intl }, } = this.props; const { hasError, hasLoaded } = this.state; const hasImage = (source || customer) && !hasError; const nameString = name || initials; let finalSource; let label; if (accessibilityLabel) { label = accessibilityLabel; } else if (name) { label = name; } else if (initials) { const splitInitials = initials.split('').join(' '); label = intl.translate('Polaris.Avatar.labelWithInitials', { initials: splitInitials, }); } else { label = intl.translate('Polaris.Avatar.label'); } if (source) { finalSource = source; } else if (customer) { finalSource = customerPlaceholder(nameString); } const className = classNames(styles.Avatar, styles[variationName('style', styleClass(nameString))], size && styles[variationName('size', size)], hasImage && !hasLoaded && styles.hidden, hasImage && styles.hasImage); const imageMarkUp = finalSource && !isServer && !hasError ? (<Image className={styles.Image} source={finalSource} alt="" role="presentation" onLoad={this.handleLoad} onError={this.handleError}/>) : null; // Use `dominant-baseline: central` instead of `dy` when Edge supports it. const verticalOffset = '0.35em'; const initialsMarkup = initials && !hasImage ? (<span className={styles.Initials}> <svg className={styles.Svg} viewBox="0 0 48 48"> <text x="50%" y="50%" dy={verticalOffset} fill="currentColor" fontSize="26" textAnchor="middle"> {initials} </text> </svg> </span>) : null; return (<span aria-label={label} role="img" className={className}> {initialsMarkup} {imageMarkUp} </span>); } } function styleClass(name) { return name ? STYLE_CLASSES[name.charCodeAt(0) % STYLE_CLASSES.length] : STYLE_CLASSES[0]; } function customerPlaceholder(name) { return name ? AVATAR_IMAGES[name.charCodeAt(0) % AVATAR_IMAGES.length] : AVATAR_IMAGES[0]; } export default withAppProvider()(Avatar);