UNPKG

@gravityforms/components

Version:

UI components for use in Gravity Forms development. Both React and vanilla js flavors.

188 lines (174 loc) 6.26 kB
import { React, classnames } from '@gravityforms/libraries'; import { useId } from '@gravityforms/react-utils'; import { spacerClasses } from '@gravityforms/utils'; import FileUpload from '../../elements/FileUpload'; import Droplist from '../Droplist'; import { generateComplementaryGradient } from './utils'; const { forwardRef } = React; /** * @module Banner * @description Renders a banner component with optional file upload. * * @since 5.6.0 * * @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 {Record<string, any>} [fileUploadAttributes] - Custom attributes for the file upload component * @param {boolean} [hasActions=false] - Whether to show the actions droplist * @param {boolean} [hasUpload=false] - Whether to show the file upload * @param {string} [height=''] - The height of the component * @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 component * @param {string} [noImageGradient=''] - The gradient for the component * @param {string} [noImageGradientColor=''] - The gradient color for the component * @param {object} [noImageGradientLayout] - The optional gradient layout for the component * @param {Record<string, any>} [removeButtonAttributes] - Custom attributes for the remove button * @param {Record<string, any>} [selectButtonAttributes] - Custom attributes for the select button * @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 banner component. * * @example * import Banner from '@gravityforms/components/react/admin/modules/Banner'; * * return ( * <Banner> * { 'children' } * </Banner> * ); * */ const Banner = forwardRef( ( { children = null, customAttributes = {}, customClasses = [], droplistAttributes = {}, droplistClasses = [], fileUploadAttributes = {}, hasActions = false, hasUpload = false, height = '', i18n = {}, id: idProp = '', imageFile = '', noImageGradient = '', noImageGradientColor = '', noImageGradientLayout = null, removeButtonAttributes = {}, selectButtonAttributes = {}, spacing = '', uploadButtonAttributes = {}, }, ref ) => { const id = useId( idProp ); const style = {}; // Apply image background if provided if ( ! hasUpload && imageFile ) { style.backgroundImage = `url(${ imageFile })`; } // Apply height if provided if ( height ) { style.height = height; } // Apply gradient or background color if ( ! imageFile ) { if ( noImageGradientColor ) { style.backgroundColor = noImageGradientColor; // Generate complementary gradient if no predefined gradient is set if ( ! noImageGradient ) { style.backgroundImage = generateComplementaryGradient( noImageGradientColor, noImageGradientLayout ); style.backgroundBlendMode = 'normal'; } } } const bannerProps = { className: classnames( { 'gform-banner': true, 'gform-banner--has-image': imageFile.length > 0, [ `gform-gradient--${ noImageGradient }` ]: ( ( ! hasUpload && ! imageFile ) || hasUpload ) && noImageGradient.length > 0, ...spacerClasses( spacing ), }, customClasses ), ref, style, ...customAttributes, }; const fileUploadProps = { fileURL: imageFile, ...fileUploadAttributes, }; 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, }, }, ]; if ( imageFile ) { listItems.push( { key: 'remove', props: { element: 'button', iconBefore: 'trash', iconPrefix: 'gravity-component-icon', label: i18n?.remove || '', ...removeButtonAttributes, }, } ); } const droplistProps = { align: 'right', closeOnClick: true, customClasses: classnames( [ 'gform-banner__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', ...( droplistAttributes?.triggerAttributes || {} ), }, }; return ( <div { ...bannerProps }> { hasUpload && <FileUpload { ...fileUploadProps } /> } { hasActions && <Droplist { ...droplistProps } /> } { children } </div> ); } ); Banner.displayName = 'Banner'; export default Banner;