Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
/* 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;