UNPKG

@gravityforms/components

Version:

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

288 lines (258 loc) 7.86 kB
import { React, ReactRouter, PropTypes, classnames } from '@gravityforms/libraries'; import { uniqueId } from '@gravityforms/utils'; import Button from '../../elements/Button'; import Icon from '../../elements/Icon'; import Text from '../../elements/Text'; const { forwardRef } = React; const { Link } = ReactRouter; /** * @module RouterNavBar * @description The main nav used in various admin apps, using react router. * * @since 3.3.2 * * @param {object} props Component props. * @param {JSX.Element} props.children React element children. * @param {object} props.customAttributes Custom attributes for the component. * @param {string|Array|object} props.customClasses Custom classes for the component. * @param {function} props.handleNavigationBlocked Callback function to handle navigation blocked. * @param {Array} props.items The nav items. * @param {boolean} props.navigationBlocked Whether navigation is blocked. * @param {string} props.type The type of the nav bar, one of `icon-button` or `icon-text-tag`. * @param {object|null} ref Ref to the component. * * @return {JSX.Element} The RouterNavBar component. * * @example * import RouterNavBar from '@gravityforms/components/react/admin/modules/RouterNavBar'; * * const items = [ * { * item: { active: true, key: 'send-a-test' }, * link: { to: '/send-a-test' }, * icon: { icon: 'beaker', iconPrefix: 'gravitysmtp-admin-icon' }, * text: { content: 'Send a test' }, * }, * { * item: { active: true, key: 'scheduled-events' }, * link: { to: '/scheduled-events' }, * icon: { icon: 'clock', iconPrefix: 'gravitysmtp-admin-icon' }, * text: { content: 'Scheduled events' }, * }, * ]; * * return <RouterNavBar items={ items } />; * */ const RouterNavBar = forwardRef( ( { children = null, customAttributes = {}, customClasses = [], handleNavigationBlocked = () => {}, items = [], navigationBlocked = false, type = 'icon-button', }, ref ) => { const navAttributes = { className: classnames( [ 'gform-router-nav-bar', `gform-router-nav-bar--${ type }`, ], customClasses ), ...customAttributes, }; const isIconButton = type === 'icon-button'; const handleLinkClick = ( event ) => { if ( navigationBlocked ) { event.preventDefault(); const linkElement = event.target.closest( 'a' ); if ( linkElement ) { handleNavigationBlocked( linkElement.href ); } } }; const getIconButtonItems = () => { return items.map( ( item ) => { const { item: { customClasses: itemCustomClasses, key: itemKey, active: itemActive, disabled: itemDisabled, ...itemProps }, icon: { customClasses: iconCustomClasses, ...iconProps }, text: { customClasses: textCustomClasses, ...textProps }, } = item; const textId = uniqueId( 'gform-router-nav-bar__item-text-' ); const itemAttrs = { className: classnames( { 'gform-router-nav-bar__item': true, 'gform-router-nav-bar__item--active': itemActive, 'gform-router-nav-bar__item--disabled': itemDisabled, }, itemCustomClasses || [] ), ...itemProps, }; const iconAttrs = { customClasses: classnames( [ 'gform-router-nav-bar__item-icon' ], iconCustomClasses || [] ), ...iconProps, }; const textAttrs = { customAttributes: { id: textId, }, customClasses: classnames( [ 'gform-router-nav-bar__item-text' ], textCustomClasses || [] ), size: 'text-xs', tagName: 'span', weight: 'medium', ...textProps, }; if ( item.link ) { const { customClasses: linkCustomClasses, ...linkProps } = item.link; const linkAttrs = { 'aria-labelledby': textId, className: classnames( [ 'gform-router-nav-bar__item-link', 'gform-button', 'gform-button--icon-white', 'gform-button--size-height-m', ], linkCustomClasses || [] ), ...linkProps, onClick: handleLinkClick, }; return ( <li { ...itemAttrs } key={ itemKey }> <Link { ...linkAttrs }> <Icon { ...iconAttrs } /> </Link> <Text { ...textAttrs } /> </li> ); } else if ( item.button ) { const { customClasses: buttonCustomClasses, ...buttonProps } = item.button; const buttonAttrs = { 'aria-labelledby': textId, customClasses: classnames( [ 'gform-router-nav-bar__item-button', ], buttonCustomClasses || [] ), ...buttonProps, }; return ( <li { ...itemAttrs } key={ itemKey }> <Button { ...buttonAttrs }> <Icon { ...iconAttrs } /> </Button> <Text { ...textAttrs } /> </li> ); } return null; } ); }; const getIconTextTagItems = () => { return items.map( ( item ) => { const { item: { customClasses: itemCustomClasses, key: itemKey, active: itemActive, disabled: itemDisabled, ...itemProps }, text: { customClasses: textCustomClasses, ...textProps }, } = item; const itemAttrs = { className: classnames( { 'gform-router-nav-bar__item': true, 'gform-router-nav-bar__item--active': itemActive, 'gform-router-nav-bar__item--disabled': itemDisabled, }, itemCustomClasses || [] ), ...itemProps, }; const hasIcon = !! item?.icon; let iconAttrs = {}; if ( hasIcon ) { const { customClasses: iconCustomClasses, ...iconProps } = item.icon; iconAttrs = { customClasses: classnames( [ 'gform-router-nav-bar__item-icon' ], iconCustomClasses || [] ), ...iconProps, }; } const textAttrs = { customClasses: classnames( [ 'gform-router-nav-bar__item-text' ], textCustomClasses || [] ), size: 'text-sm', tagName: 'span', weight: 'medium', ...textProps, }; if ( item.link ) { const { customClasses: linkCustomClasses, ...linkProps } = item.link; const linkAttrs = { className: classnames( [ 'gform-router-nav-bar__item-link' ], linkCustomClasses || [] ), ...linkProps, onClick: handleLinkClick, }; return ( <li { ...itemAttrs } key={ itemKey }> <Link { ...linkAttrs }> { hasIcon && <Icon { ...iconAttrs } /> } <Text { ...textAttrs } /> </Link> </li> ); } else if ( item.button ) { const { customClasses: buttonCustomClasses, ...buttonProps } = item.button; const buttonAttrs = { customClasses: classnames( [ 'gform-router-nav-bar__item-button' ], buttonCustomClasses || [] ), ...buttonProps, }; return ( <li { ...itemAttrs } key={ itemKey }> <Button { ...buttonAttrs }> { hasIcon && <Icon { ...iconAttrs } /> } <Text { ...textAttrs } /> </Button> </li> ); } return null; } ); }; const getItems = () => { if ( items.length === 0 ) { return null; } return ( <ul className="gform-router-nav-bar__list"> { isIconButton ? getIconButtonItems() : getIconTextTagItems() } </ul> ); }; return ( <nav { ...navAttributes } ref={ ref }> { getItems() } { children } </nav> ); } ); RouterNavBar.propTypes = { children: PropTypes.oneOfType( [ PropTypes.arrayOf( PropTypes.node ), PropTypes.node, ] ), customAttributes: PropTypes.object, customClasses: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array, PropTypes.object, ] ), items: PropTypes.arrayOf( PropTypes.shape( { item: PropTypes.object, link: PropTypes.object, icon: PropTypes.object, text: PropTypes.object, } ) ), navigationBlocked: PropTypes.bool, type: PropTypes.oneOf( [ 'icon-button', 'icon-text-tag' ] ), }; RouterNavBar.displayName = 'RouterNavBar'; export default RouterNavBar;