UNPKG

@hakuna-matata-ui/avatar

Version:

A React component used to show users avatar or initials

354 lines (305 loc) 10.9 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var image = require('@hakuna-matata-ui/image'); var system = require('@hakuna-matata-ui/system'); var utils = require('@hakuna-matata-ui/utils'); var React = require('react'); var reactUtils = require('@hakuna-matata-ui/react-utils'); function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespace(React); function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } var _excluded$1 = ["name", "getInitials"], _excluded2 = ["src", "name", "showBorder", "borderRadius", "onError", "getInitials", "icon", "iconLabel", "loading", "children", "borderColor", "ignoreFallback"]; /** * AvatarBadge used to show extra badge to the top-right * or bottom-right corner of an avatar. */ var AvatarBadge = /*#__PURE__*/system.forwardRef(function (props, ref) { var styles = system.useStyles(); var badgeStyles = _extends({ position: "absolute", display: "flex", alignItems: "center", justifyContent: "center", insetEnd: "0", bottom: "0" }, styles.badge); return /*#__PURE__*/React__namespace.createElement(system.chakra.div, _extends({ ref: ref }, props, { className: utils.cx("chakra-avatar__badge", props.className), __css: badgeStyles })); }); if (utils.__DEV__) { AvatarBadge.displayName = "AvatarBadge"; } function initials(name) { var _name$split = name.split(" "), firstName = _name$split[0], lastName = _name$split[1]; return firstName && lastName ? "" + firstName.charAt(0) + lastName.charAt(0) : firstName.charAt(0); } /** * The avatar name container */ var AvatarName = function AvatarName(props) { var name = props.name, getInitials = props.getInitials, rest = _objectWithoutPropertiesLoose(props, _excluded$1); var styles = system.useStyles(); return /*#__PURE__*/React__namespace.createElement(system.chakra.div, _extends({ role: "img", "aria-label": name }, rest, { __css: styles.label }), name ? getInitials == null ? void 0 : getInitials(name) : null); }; /** * Fallback avatar react component. * This should be a generic svg used to represent an avatar */ var DefaultIcon = function DefaultIcon(props) { return /*#__PURE__*/React__namespace.createElement(system.chakra.svg, _extends({ viewBox: "0 0 128 128", color: "#fff", width: "100%", height: "100%", className: "chakra-avatar__svg" }, props), /*#__PURE__*/React__namespace.createElement("path", { fill: "currentColor", d: "M103,102.1388 C93.094,111.92 79.3504,118 64.1638,118 C48.8056,118 34.9294,111.768 25,101.7892 L25,95.2 C25,86.8096 31.981,80 40.6,80 L87.4,80 C96.019,80 103,86.8096 103,95.2 L103,102.1388 Z" }), /*#__PURE__*/React__namespace.createElement("path", { fill: "currentColor", d: "M63.9961647,24 C51.2938136,24 41,34.2938136 41,46.9961647 C41,59.7061864 51.2938136,70 63.9961647,70 C76.6985159,70 87,59.7061864 87,46.9961647 C87,34.2938136 76.6985159,24 63.9961647,24" })); }; var baseStyle = { display: "inline-flex", alignItems: "center", justifyContent: "center", textAlign: "center", textTransform: "uppercase", fontWeight: "medium", position: "relative", flexShrink: 0 }; /** * Avatar component that renders an user avatar with * support for fallback avatar and name-only avatars */ var Avatar = /*#__PURE__*/system.forwardRef(function (props, ref) { var styles = system.useMultiStyleConfig("Avatar", props); var _omitThemingProps = system.omitThemingProps(props), src = _omitThemingProps.src, name = _omitThemingProps.name, showBorder = _omitThemingProps.showBorder, _omitThemingProps$bor = _omitThemingProps.borderRadius, borderRadius = _omitThemingProps$bor === void 0 ? "full" : _omitThemingProps$bor, onError = _omitThemingProps.onError, _omitThemingProps$get = _omitThemingProps.getInitials, getInitials = _omitThemingProps$get === void 0 ? initials : _omitThemingProps$get, _omitThemingProps$ico = _omitThemingProps.icon, icon = _omitThemingProps$ico === void 0 ? /*#__PURE__*/React__namespace.createElement(DefaultIcon, null) : _omitThemingProps$ico, _omitThemingProps$ico2 = _omitThemingProps.iconLabel, iconLabel = _omitThemingProps$ico2 === void 0 ? " avatar" : _omitThemingProps$ico2, loading = _omitThemingProps.loading, children = _omitThemingProps.children, borderColor = _omitThemingProps.borderColor, ignoreFallback = _omitThemingProps.ignoreFallback, rest = _objectWithoutPropertiesLoose(_omitThemingProps, _excluded2); var avatarStyles = _extends({ borderRadius: borderRadius, borderWidth: showBorder ? "2px" : undefined }, baseStyle, styles.container); if (borderColor) { avatarStyles.borderColor = borderColor; } return /*#__PURE__*/React__namespace.createElement(system.chakra.span, _extends({ ref: ref }, rest, { className: utils.cx("chakra-avatar", props.className), __css: avatarStyles }), /*#__PURE__*/React__namespace.createElement(system.StylesProvider, { value: styles }, /*#__PURE__*/React__namespace.createElement(AvatarImage, { src: src, loading: loading, onError: onError, getInitials: getInitials, name: name, borderRadius: borderRadius, icon: icon, iconLabel: iconLabel, ignoreFallback: ignoreFallback }), children)); }); if (utils.__DEV__) { Avatar.displayName = "Avatar"; } var AvatarImage = function AvatarImage(props) { var src = props.src, onError = props.onError, getInitials = props.getInitials, name = props.name, borderRadius = props.borderRadius, loading = props.loading, iconLabel = props.iconLabel, _props$icon = props.icon, icon = _props$icon === void 0 ? /*#__PURE__*/React__namespace.createElement(DefaultIcon, null) : _props$icon, ignoreFallback = props.ignoreFallback; /** * use the image hook to only show the image when it has loaded */ var status = image.useImage({ src: src, onError: onError, ignoreFallback: ignoreFallback }); var hasLoaded = status === "loaded"; /** * Fallback avatar applies under 2 conditions: * - If `src` was passed and the image has not loaded or failed to load * - If `src` wasn't passed * * In this case, we'll show either the name avatar or default avatar */ var showFallback = !src || !hasLoaded; if (showFallback) { return name ? /*#__PURE__*/React__namespace.createElement(AvatarName, { className: "chakra-avatar__initials", getInitials: getInitials, name: name }) : /*#__PURE__*/React__namespace.cloneElement(icon, { role: "img", "aria-label": iconLabel }); } /** * If `src` was passed and the image has loaded, we'll show it */ return /*#__PURE__*/React__namespace.createElement(system.chakra.img, { src: src, alt: name, className: "chakra-avatar__img", loading: loading, __css: { width: "100%", height: "100%", objectFit: "cover", borderRadius: borderRadius } }); }; if (utils.__DEV__) { AvatarImage.displayName = "AvatarImage"; } var _excluded = ["children", "borderColor", "max", "spacing", "borderRadius"]; /** * AvatarGroup displays a number of avatars grouped together in a stack. */ var AvatarGroup = /*#__PURE__*/system.forwardRef(function (props, ref) { var styles = system.useMultiStyleConfig("Avatar", props); var _omitThemingProps = system.omitThemingProps(props), children = _omitThemingProps.children, borderColor = _omitThemingProps.borderColor, max = _omitThemingProps.max, _omitThemingProps$spa = _omitThemingProps.spacing, spacing = _omitThemingProps$spa === void 0 ? "-0.75rem" : _omitThemingProps$spa, _omitThemingProps$bor = _omitThemingProps.borderRadius, borderRadius = _omitThemingProps$bor === void 0 ? "full" : _omitThemingProps$bor, rest = _objectWithoutPropertiesLoose(_omitThemingProps, _excluded); var validChildren = reactUtils.getValidChildren(children); /** * get the avatars within the max */ var childrenWithinMax = max ? validChildren.slice(0, max) : validChildren; /** * get the remaining avatar count */ var excess = max != null && validChildren.length - max; /** * Reversing the children is a great way to avoid using zIndex * to overlap the avatars */ var reversedChildren = childrenWithinMax.reverse(); var clones = reversedChildren.map(function (child, index) { var _child$props$borderCo; var isFirstAvatar = index === 0; var childProps = { marginEnd: isFirstAvatar ? 0 : spacing, size: props.size, borderColor: (_child$props$borderCo = child.props.borderColor) != null ? _child$props$borderCo : borderColor, showBorder: true }; return /*#__PURE__*/React__namespace.cloneElement(child, utils.filterUndefined(childProps)); }); var groupStyles = { display: "flex", alignItems: "center", justifyContent: "flex-end", flexDirection: "row-reverse" }; var excessStyles = _extends({ borderRadius: borderRadius, marginStart: spacing }, baseStyle, styles.excessLabel); return /*#__PURE__*/React__namespace.createElement(system.chakra.div, _extends({ ref: ref, role: "group", __css: groupStyles }, rest, { className: utils.cx("chakra-avatar__group", props.className) }), excess > 0 && /*#__PURE__*/React__namespace.createElement(system.chakra.span, { className: "chakra-avatar__excess", __css: excessStyles }, "+" + excess), clones); }); if (utils.__DEV__) { AvatarGroup.displayName = "AvatarGroup"; } exports.Avatar = Avatar; exports.AvatarBadge = AvatarBadge; exports.AvatarGroup = AvatarGroup; exports.baseStyle = baseStyle;