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 {Array} props.items The nav items.
* @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 = [],
items = [],
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 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,
};
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,
};
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,
} ) ),
type: PropTypes.oneOf( [ 'icon-button', 'icon-text-tag' ] ),
};
RouterNavBar.displayName = 'RouterNavBar';
export default RouterNavBar;