UNPKG

@shopify/polaris

Version:

Shopify’s product component library

83 lines (82 loc) 3.26 kB
import React, { useState, useCallback, useEffect } from 'react'; import { classNames, variationName } from '../../utilities/css'; import { useI18n } from '../../utilities/i18n'; import { isServer } from '../../utilities/target'; import { Image } from '../Image'; import styles from './Avatar.scss'; import * as avatars from './images'; var Status; (function (Status) { Status["Pending"] = "PENDING"; Status["Loaded"] = "LOADED"; Status["Errored"] = "ERRORED"; })(Status || (Status = {})); 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 function Avatar({ name, source, initials, customer, size = 'medium', accessibilityLabel, }) { const i18n = useI18n(); const [status, setStatus] = useState(Status.Pending); // If the source changes, set the status back to pending useEffect(() => { setStatus(Status.Pending); }, [source]); const handleError = useCallback(() => { setStatus(Status.Errored); }, []); const handleLoad = useCallback(() => { setStatus(Status.Loaded); }, []); const hasImage = (source || customer) && status !== Status.Errored; 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 = i18n.translate('Polaris.Avatar.labelWithInitials', { initials: splitInitials, }); } else { label = i18n.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 && status !== Status.Loaded && styles.hidden, hasImage && styles.hasImage); const imageMarkUp = finalSource && !isServer && status !== Status.Errored ? (<Image className={styles.Image} source={finalSource} alt="" role="presentation" onLoad={handleLoad} onError={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]; }