UNPKG

react-avatar

Version:

Universal React avatar component makes it possible to generate avatars based on user information.

142 lines (135 loc) 4.8 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React from 'react'; import PropTypes from 'prop-types'; import Wrapper from './wrapper'; import { parseSize, setGroupedTimeout, calculateBorderRadius, getNullableText } from '../utils'; export default class AvatarText extends React.PureComponent { constructor() { var _this; super(...arguments); _this = this; _defineProperty(this, "_scaleTextNode", function (node) { let retryTTL = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 16; const { unstyled, textSizeRatio, textMarginRatio, avatar } = _this.props; _this._node = node; if (!node || !node.parentNode || unstyled || avatar.src || !_this._mounted) return; const spanNode = node.parentNode; const tableNode = spanNode.parentNode; const { width: containerWidth, height: containerHeight } = spanNode.getBoundingClientRect(); // Whenever the avatar element is not visible due to some CSS // (such as display: none) on any parent component we will check // whether the component has become visible. // // The time between checks grows up to half a second in an attempt // to reduce flicker / performance issues. if (containerWidth == 0 && containerHeight == 0) { const ttl = Math.min(retryTTL * 1.5, 500); setGroupedTimeout(() => _this._scaleTextNode(node, ttl), ttl); return; } // If the tableNode (outer-container) does not have its fontSize set yet, // we'll set it according to "textSizeRatio" if (!tableNode.style.fontSize) { const baseFontSize = containerHeight / textSizeRatio; tableNode.style.fontSize = "".concat(baseFontSize, "px"); } // Reset font-size such that scaling works correctly (#133) spanNode.style.fontSize = null; // Measure the actual width of the text after setting the container size const { width: textWidth } = node.getBoundingClientRect(); if (textWidth < 0) return; // Calculate the maximum width for the text based on "textMarginRatio" const maxTextWidth = containerWidth * (1 - 2 * textMarginRatio); // If the text is too wide, scale it down by (maxWidth / actualWidth) if (textWidth > maxTextWidth) spanNode.style.fontSize = "calc(1em * ".concat(maxTextWidth / textWidth, ")"); }); } componentDidMount() { this._mounted = true; this._scaleTextNode(this._node); } componentWillUnmount() { this._mounted = false; } render() { const { className, round, unstyled, title, name, value, avatar } = this.props; const size = parseSize(this.props.size); const initialsStyle = unstyled ? null : { width: size.str, height: size.str, lineHeight: 'initial', textAlign: 'center', color: this.props.fgColor, background: avatar.color, borderRadius: calculateBorderRadius(round) }; const tableStyle = unstyled ? null : { display: 'table', tableLayout: 'fixed', width: '100%', height: '100%' }; const spanStyle = unstyled ? null : { display: 'table-cell', verticalAlign: 'middle', fontSize: '100%', whiteSpace: 'nowrap' }; // Ensure the text node is updated and scaled when any of these // values changed by calling the `_scaleTextNode` method using // the correct `ref`. const key = [avatar.value, this.props.size].join(''); return /*#__PURE__*/React.createElement(Wrapper, this.props, /*#__PURE__*/React.createElement("div", { className: className + ' sb-avatar__text', style: initialsStyle, title: getNullableText(title, name || value) }, /*#__PURE__*/React.createElement("div", { style: tableStyle }, /*#__PURE__*/React.createElement("span", { style: spanStyle }, /*#__PURE__*/React.createElement("span", { ref: this._scaleTextNode, key: key }, avatar.value))))); } } _defineProperty(AvatarText, "propTypes", { name: PropTypes.string, value: PropTypes.string, avatar: PropTypes.object, title: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), className: PropTypes.string, unstyled: PropTypes.bool, fgColor: PropTypes.string, textSizeRatio: PropTypes.number, textMarginRatio: PropTypes.number, round: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.number]), size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]) }); _defineProperty(AvatarText, "defaultProps", { className: '', fgColor: '#FFF', round: false, size: 100, textSizeRatio: 3, textMarginRatio: .15, unstyled: false });