UNPKG

@gravityforms/components

Version:

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

159 lines (148 loc) 4.98 kB
import { classnames, PropTypes, React } from '@gravityforms/libraries'; import { ConditionalWrapper, useStateWithDep } from '@gravityforms/react-utils'; import { spacerClasses } from '@gravityforms/utils'; import Button from '../../elements/Button'; const { forwardRef } = React; /** * @module MetaBox * @description A metabox component with optional header and footer. * * @since 1.1.15 * * @param {object} props Component props. * @param {boolean} props.collapsible Whether the meta box is collapsible. * @param {string} props.collapsibleIcon The icon for the collapsible button. * @param {string} props.collapsibleIconPrefix The icon prefix for the collapsible button. * @param {boolean} props.collapsed Whether the meta box is collapsed. * @param {string} props.contentId The ID for the content, used for a11y when collapsible is true. * @param {JSX.Element} props.children React element children. * @param {object} props.customAttributes Custom attributes for the layout. * @param {string|Array|object} props.customClasses Custom classes for the layout. * @param {JSX.Element} props.HeaderContent The header element. * @param {object} props.i18n Internationalization object. * @param {JSX.Element} props.FooterContent The footer element. * @param {string|number|Array|object} props.spacing The spacing for the component, as a string, number, array, or object. * @param {string} props.tagName The tag name for the layout. * * @return {JSX.Element} The MetaBox component. * @example * import MetaBox from '@gravityforms/components/admin/modules/MetaBox'; * * const HeaderContent = ( props ) => <SomeComponent { ...props } />; * const FooterContent = ( props ) => <SomeComponent { ...props } />; * * <MetaBox * HeaderContent={ HeaderContent } * FooterContent={ FooterContent } * customClasses={ 'my-custom-class' } * customAttributes={ { 'data-custom-attribute': 'custom' } } * tagName={ 'section' } * > * <div>Content</div> *</MetaBox> * */ const MetaBox = forwardRef( ( { children = null, collapsible = false, collapsibleIcon = 'accordion-arrow', collapsibleIconPrefix = 'gravity-component-icon', collapsed = false, contentId = '', customAttributes = {}, customClasses = {}, FooterContent = null, HeaderContent = null, i18n = {}, spacing = '', tagName = 'div', ...props }, ref ) => { const [ isCollapsed, setIsCollapsed ] = useStateWithDep( collapsed ); const { collapsedAriaLabel = '', expandedAriaLabel = '', } = i18n; const componentProps = { className: classnames( { 'gform-meta-box': true, 'gform-meta-box--is-collapsible': collapsible, 'gform-meta-box--is-collapsed': isCollapsed, ...spacerClasses( spacing ), }, customClasses ), ...customAttributes, 'data-testid': 'gform-meta-box', ref, }; const toggleButtonProps = { customAttributes: { 'aria-controls': contentId ? contentId : undefined, 'aria-expanded': ! isCollapsed, 'aria-label': isCollapsed ? collapsedAriaLabel : expandedAriaLabel, }, customClasses: [ 'gform-meta-box__toggle' ], icon: collapsibleIcon, iconAttributes: { customClasses: [ 'gform-meta-box__toggle-icon' ], }, iconPrefix: collapsibleIconPrefix, onClick: () => setIsCollapsed( ! isCollapsed ), type: 'unstyled', }; const Container = tagName; return ( <Container { ...componentProps }> { HeaderContent && <div className="gform-meta-box__header" data-testid="gform-meta-box-header" > <ConditionalWrapper condition={ collapsible } wrapper={ ( ch ) => <Button { ...toggleButtonProps }>{ ch }</Button> } > <HeaderContent { ...props } /> </ConditionalWrapper> </div> } <div className="gform-meta-box__content" id={ contentId ? contentId : undefined } style={ { display: isCollapsed ? 'none' : '' } } > { children } </div> { FooterContent && <div className="gform-meta-box__footer" data-testid="gform-meta-box-footer" > <FooterContent { ...props } /> </div> } </Container> ); } ); MetaBox.propTypes = { children: PropTypes.oneOfType( [ PropTypes.arrayOf( PropTypes.node ), PropTypes.node, ] ), customAttributes: PropTypes.object, customClasses: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array, PropTypes.object, ] ), FooterContent: PropTypes.func, HeaderContent: PropTypes.func, spacing: PropTypes.oneOfType( [ PropTypes.string, PropTypes.number, PropTypes.array, PropTypes.object, ] ), tagName: PropTypes.string, }; MetaBox.displayName = 'MetaBox'; export default MetaBox;