UNPKG

@gravityforms/components

Version:

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

220 lines (207 loc) 6.98 kB
import { classnames, React } from '@gravityforms/libraries'; import { ConditionalWrapper } from '@gravityforms/react-utils'; import { spacerClasses } from '@gravityforms/utils'; import Grid from '../../../elements/Grid'; const { forwardRef } = React; // Helper Functions const getWrapperProps = ( { animated = true, spacing = 2, wrapperAttributes = {}, wrapperClasses = [], } ) => ( { className: classnames( 'gform-placeholder__wrapper', { 'gform-placeholder__wrapper--animated': animated }, spacerClasses( spacing ), wrapperClasses ), ...wrapperAttributes, } ); const getPlaceholderProps = ( { borderRadius = '9999px', customClasses = [], customAttributes = {}, height = '14px', gridCount = 1, gridItemSpacing = 0, gridItemWidth = 90, width = '100%', } ) => ( { className: classnames( 'gform-placeholder', { 'gform-grid--item': gridCount > 1 }, spacerClasses( gridItemSpacing ), customClasses ), style: { borderRadius, height, width: gridCount > 1 ? `${ gridItemWidth / gridCount }%` : width, }, ...customAttributes, } ); const getMergedGridProps = ( gridProps = {} ) => ( { alignItems: 'center', container: true, direction: 'row', elementType: 'div', justifyContent: 'space-between', ...gridProps, } ); // PlaceholderStripe Component const PlaceholderStripe = ( { gridCount, gridProps, placeholderProps, wrapperProps, } ) => ( <div { ...wrapperProps }> <ConditionalWrapper condition={ gridCount > 1 } wrapper={ ( children ) => <Grid { ...gridProps }>{ children }</Grid> } > { Array( gridCount ) .fill( 0 ) .map( ( _, index ) => ( <span key={ `placeholder-${ index }` } { ...placeholderProps } /> ) ) } </ConditionalWrapper> </div> ); /** * @module Placeholder * @description A component that renders single or grouped placeholder stripes with optional * opacity animations and grid layout. Useful for loading states or content placeholders. * * @since 4.5.0 * * @param {object} props - Component props * @param {boolean} [props.animated] - Whether to include animation effects * @param {string} [props.borderRadius] - Border radius of placeholder stripes * @param {object} [props.customAttributes] - Custom HTML attributes for placeholder elements * @param {string|string[]|object} [props.customClasses] - Additional CSS classes for placeholder elements * @param {number} [props.gridCount] - Number of placeholder stripes in a single row * @param {number} [props.gridItemSpacing] - Spacing between grid items when in a row using grid count * @param {number} [props.gridItemWidth] - Width of each grid item as a percentage * @param {object} [props.gridProps] - Props to pass to the Grid component * @param {object[]} [props.groupData] - Array of group configurations for multiple placeholder sets * @param {string} [props.height] - Height of placeholder stripes * @param {number} [props.rows] - Number of rows. This overrides groupData if set. * @param {string|number|string[]|object} [props.spacing] - Spacing between elements * @param {string} [props.width] - Width of placeholder stripes * @param {object} [props.wrapperAttributes] - Custom HTML attributes for wrapper element * @param {string|string[]|object} [props.wrapperClasses] - Additional CSS classes for wrapper * @param {object|null} props.ref - Forwarded ref to the component * * @return {JSX.Element} A placeholder component with configurable stripes and layout * * @example * // Single placeholder * <Placeholder height="20px" width="50%" animated={true} /> * * // Grid of placeholders * <Placeholder gridCount={3} spacing={4} /> * * // Grouped placeholders * <Placeholder * groupData={[ * { gridCount: 2, height: '20px' }, * { gridCount: 3, height: '15px', animated: false } * ]} * /> */ const Placeholder = forwardRef( ( { animated = true, borderRadius = '9999px', customAttributes = {}, customClasses = [], gridCount = 1, gridItemSpacing = 0, gridItemWidth = 90, gridProps = {}, groupData = [], height = '14px', rows = 1, spacing = 2, width = '100%', wrapperAttributes = {}, wrapperClasses = [], }, ref ) => { if ( ! groupData.length && rows === 1 ) { const wrapperProps = { ...getWrapperProps( { animated, spacing, wrapperAttributes, wrapperClasses } ), ref, }; return ( <PlaceholderStripe gridCount={ gridCount } gridProps={ getMergedGridProps( gridProps ) } placeholderProps={ getPlaceholderProps( { borderRadius, customClasses, customAttributes, height, gridCount, gridItemSpacing, gridItemWidth, width, } ) } wrapperProps={ wrapperProps } /> ); } // if we just want to use global prop data for each row, fill out the groupData array with empty objects if ( ! groupData.length ) { groupData = Array( rows ).fill( {} ); } return ( <div className="gform-placeholder__group-container"> { groupData.map( ( group, index ) => { const { animated: groupAnimated = animated, borderRadius: groupBorderRadius = borderRadius, customAttributes: groupCustomAttributes = customAttributes, customClasses: groupCustomClasses = customClasses, gridCount: groupGridCount = gridCount, gridItemSpacing: groupGridItemSpacing = gridItemSpacing, gridItemWidth: groupGridItemWidth = gridItemWidth, gridProps: groupGridProps = gridProps, height: groupHeight = height, spacing: groupSpacing = spacing, width: groupWidth = width, wrapperAttributes: groupWrapperAttributes = wrapperAttributes, wrapperClasses: groupWrapperClasses = wrapperClasses, } = group; return ( <PlaceholderStripe key={ `placeholder-group-${ index }` } gridCount={ groupGridCount } gridProps={ getMergedGridProps( groupGridProps ) } placeholderProps={ getPlaceholderProps( { borderRadius: groupBorderRadius, customClasses: groupCustomClasses, customAttributes: groupCustomAttributes, height: groupHeight, gridCount: groupGridCount, gridItemSpacing: groupGridItemSpacing, gridItemWidth: groupGridItemWidth, width: groupWidth, } ) } wrapperProps={ getWrapperProps( { animated: groupAnimated, spacing: groupSpacing, wrapperAttributes: groupWrapperAttributes, wrapperClasses: groupWrapperClasses, } ) } /> ); } ) } </div> ); } ); Placeholder.displayName = 'Loaders/Placeholder'; export default Placeholder;