@gravityforms/components
Version:
UI components for use in Gravity Forms development. Both React and vanilla js flavors.
195 lines (180 loc) • 7 kB
JavaScript
import { React, classnames } from '@gravityforms/libraries';
import { useId } from '@gravityforms/react-utils';
import { spacerClasses } from '@gravityforms/utils';
import FileUpload from '../../elements/FileUpload';
import Icon from '../../elements/Icon';
import Droplist from '../Droplist';
const { forwardRef } = React;
/**
* @module Avatar
* @description Renders an avatar component with optional file upload.
*
* @since 5.4.6
*
* @param {React.ReactNode|React.ReactNode[]} [children] - React element children
* @param {Record<string, any>} [customAttributes] - Custom attributes for the component
* @param {string|string[]|Record<string, boolean>} [customClasses] - Custom classes for the component
* @param {Record<string, any>} [droplistAttributes] - Custom attributes for the droplist component
* @param {string|string[]|Record<string, boolean>} [droplistClasses] - Custom classes for the droplist component
* @param {boolean} [hasActions=false] - Whether to show the actions droplist
* @param {boolean} [hasBorder=false] - Whether the avatar has a border
* @param {boolean} [hasUpload=false] - Whether to show the file upload
* @param {boolean} [hideInitials=false] - Whether to hide the initials
* @param {boolean} [hideLogo=false] - Whether to hide the logo
* @param {boolean} [hideNoImageIcon=false] - Whether to show the no image icon in the background.
* @param {Record<string, any>} [i18n] - The i18n strings for the component
* @param {string} [id=''] - The ID of the component
* @param {string} [imageFile=''] - The image file for the avatar
* @param {string} [initials=''] - The initials for the avatar
* @param {React.ComponentType} [Logo=null] - The logo component
* @param {string} [noImageIcon='user'] - The icon to show when no image is present
* @param {string} [noImageIconPrefix='gravity-component-icon'] - The icon prefix
* @param {Record<string, any>} [selectButtonAttributes] - Custom attributes for the select button
* @param {'2xs'|'xs'|'sm'|'md'|'lg'|'xl'|'2xl'} [size='lg'] - The size of the avatar
* @param {string|number|string[]|Record<string, any>} [spacing=''] - The spacing for the component
* @param {Record<string, any>} [uploadButtonAttributes] - Custom attributes for the upload button
* @param {React.RefObject<HTMLElement>|null} ref - Ref to the component
*
* @return {JSX.Element} The avatar component.
*
* @example
* import Avatar from '@gravityforms/components/react/admin/modules/Avatar';
*
* return (
* <Avatar>
* { 'children' }
* </Avatar>
* );
*
*/
const Avatar = forwardRef( ( {
children = null,
customAttributes = {},
customClasses = [],
droplistAttributes = {},
droplistClasses = [],
fileUploadAttributes = {},
hasActions = false,
hasBorder = false,
hasUpload = false,
hideInitials = false,
hideLogo = false,
hideNoImageIcon = false,
i18n = {},
id: idProp = '',
imageFile = '',
initials = '',
Logo = null,
noImageIcon = 'user',
noImageIconPrefix = 'gravity-component-icon',
selectButtonAttributes = {},
size = 'lg',
spacing = '',
uploadButtonAttributes = {},
}, ref ) => {
const id = useId( idProp );
const style = {};
if ( ! hasUpload && imageFile ) {
style.backgroundImage = `url(${ imageFile })`;
}
const avatarProps = {
className: classnames( {
'gform-avatar': true,
[ `gform-avatar--size-${ size }` ]: true,
'gform-avatar--has-image': imageFile.length > 0,
'gform-avatar--initials-hidden': hideInitials,
'gform-avatar--no-image-icon-hidden': hideNoImageIcon,
'gform-avatar--has-border': hasBorder,
'gform-avatar--has-upload': hasUpload,
'gform-avatar--has-actions': hasActions,
...spacerClasses( spacing ),
}, customClasses ),
ref,
...customAttributes,
};
const avatarInnerProps = {
className: 'gform-avatar__inner',
style,
};
const fileUploadProps = {
fileURL: imageFile,
uploadIcon: 'plus-regular',
...fileUploadAttributes,
};
const noImageIconProps = {
customClasses: [ 'gform-avatar__no-image-icon' ],
icon: noImageIcon,
iconPrefix: noImageIconPrefix,
};
const initialsProps = {
className: 'gform-avatar__initials',
};
const renderLogo = () => {
if ( Logo && ! hideLogo ) {
return (
<div className="gform-avatar__logo">
<Logo />
</div>
);
}
};
const listItems = [
{
key: 'upload',
props: {
element: 'button',
iconBefore: 'upload-file',
iconPrefix: 'gravity-component-icon',
label: i18n?.upload || '',
...uploadButtonAttributes,
},
},
{
key: 'select',
props: {
element: 'button',
iconBefore: 'photograph',
iconPrefix: 'gravity-component-icon',
label: i18n?.select || '',
...selectButtonAttributes,
},
},
];
const droplistProps = {
align: 'left',
closeOnClick: true,
customClasses: classnames(
[ 'gform-avatar__droplist' ],
droplistClasses || [],
),
listItems,
width: 192,
...droplistAttributes,
triggerAttributes: {
ariaId: `${ id }-droplist-aria-labelledby`,
ariaText: '',
iconPosition: 'leading',
iconPrefix: 'gravity-component-icon',
icon: 'camera-plus',
id: `${ id }-droplist-trigger`,
label: ( imageFile ? i18n?.triggerHasImage : i18n?.triggerNoImage ) || '',
size: 'size-height-s',
type: 'icon-grey',
...( droplistAttributes?.triggerAttributes || {} ),
},
};
return (
<div { ...avatarProps }>
<div { ...avatarInnerProps }>
{ hasUpload && <FileUpload { ...fileUploadProps } /> }
{ ! imageFile && ! hideInitials && <span { ...initialsProps }>{ initials }</span> }
{ ! imageFile && ! hideNoImageIcon && <Icon { ...noImageIconProps } /> }
{ children }
{ renderLogo() }
{ hasActions && <Droplist { ...droplistProps } /> }
</div>
</div>
);
} );
Avatar.displayName = 'Avatar';
export default Avatar;