Repository URL to install this package:
|
Version:
4.0.3 ▾
|
/* eslint-disable react/no-unused-prop-types */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Wrapper as RAMWrapper, Button as RAMButton, Menu as RAMMenu } from 'react-aria-menubutton';
import classNames from 'classnames';
import Icon from '../../../visuals/Icon';
import HamburgerIcon from '../../../visuals/Icon/svg/ic_menu.svg';
import UserArea from './UserArea';
import Submenu from './Submenu';
import MenuItem from './MenuItem';
import { defaultItems } from '../../../user/UserMenu/UserMenu';
import { userPropType, isLoggedIn } from '../../../utils/user';
import { translateMenuItems } from '../../../utils/translate';
import { separatorToken, submenuKey } from '../constants';
class HamburgerMenu extends Component {
constructor(props) {
super(props);
this.state = {
openSubmenus: [],
};
}
/**
* Callback required by the react-aria-menubutton. This is only used for triggering
* any action props that have been set on menu items.
*
* @param {string} selectedValue - The label of the menu item that was invoked.
*/
handleSelection = finalItems => selectedValue => {
finalItems.forEach(item => {
if (item === separatorToken) {
return;
}
const isSubmenu = submenuKey in item;
let selectedItem;
if (item.label === selectedValue) {
selectedItem = item;
} else if (isSubmenu) {
selectedItem = item.submenu.find(subItem => subItem.label === selectedValue);
}
if (selectedItem && selectedItem.action) {
selectedItem.action();
}
});
};
toggleSubmenu = item => {
const { openSubmenus } = this.state;
const newOpen = openSubmenus.includes(item.label)
? openSubmenus.filter(label => label !== item.label)
: [...openSubmenus, item.label];
this.setState({ openSubmenus: newOpen });
};
createMenuItems = () => {
const { user, items: itemsFromProps, onClickLogout, intl } = this.props;
// Add toggleSubmenu action to all submenu heads
const items = itemsFromProps.map(
item =>
submenuKey in item
? {
...item,
action: () => {
this.toggleSubmenu(item);
},
}
: item
);
// Add user items if we're logged in
if (isLoggedIn(user)) {
const userItems = translateMenuItems(defaultItems, intl);
return [
userItems[0], // Dashboard
userItems[1], // Account settings
separatorToken,
...items,
separatorToken,
{
// Log out
label: userItems[3].label,
to: onClickLogout ? null : userItems[3].to,
action: onClickLogout,
},
];
}
return items;
};
render() {
const { className, user, onClickLogin, onClickSignup } = this.props;
const { openSubmenus } = this.state;
const finalItems = this.createMenuItems();
let addSeparatorToNext = false;
return (
<RAMWrapper
tag="nav"
className={classNames('Menu', className)}
onSelection={this.handleSelection(finalItems)}
closeOnSelection={false}
>
<RAMButton
className={classNames('Button', 'Button--linkDark', 'Button--compact')}
disabled={finalItems.length === 0}
>
<Icon icon={HamburgerIcon} />
</RAMButton>
{finalItems.length > 0 && (
<RAMMenu className="HamburgerMenu-menu" tag="ul">
<UserArea user={user} onClickLogin={onClickLogin} onClickSignup={onClickSignup} />
{finalItems.map(item => {
if (item === separatorToken) {
addSeparatorToNext = true;
return null;
}
if (submenuKey in item) {
const open = openSubmenus.includes(item.label);
return (
<Submenu
head={item}
items={item.submenu}
open={open}
toggleSubmenu={this.toggleSubmenu}
key={item.label}
/>
);
}
const separatorClass = addSeparatorToNext ? 'u-separatorBefore' : '';
addSeparatorToNext = false;
return <MenuItem item={item} key={item.label} className={separatorClass} />;
})}
</RAMMenu>
)}
</RAMWrapper>
);
}
}
HamburgerMenu.propTypes = {
className: PropTypes.string,
user: userPropType,
items: PropTypes.array,
/** Will override default '/login' href if specified. */
onClickLogin: PropTypes.func,
/** Will override default '/logout' href if specified. */
onClickLogout: PropTypes.func,
/** Will override default '/signup' href if specified. */
onClickSignup: PropTypes.func,
intl: PropTypes.object,
};
HamburgerMenu.defaultProps = {
className: '',
user: null,
items: [],
onClickLogin: null,
onClickLogout: null,
onClickSignup: null,
intl: null,
};
export default HamburgerMenu;