import React from 'react'; import PropTypes from 'prop-types'; import { Link } from 'react-router-dom'; import classNames from 'classnames'; import uuid from 'uuid/v4'; import { MenuContext } from './MenuContext'; /** * Renders a collapse trigger or a ReactRouter Link */ const SidebarMenuItemLink = (props) => ( (props.to || props.href) ? ( props.to ? ( { props.children } ) : ( { props.children } ) ) : ( props.onToggle() } > { props.children } ) ) SidebarMenuItemLink.propTypes = { to: PropTypes.string, href: PropTypes.string, active: PropTypes.bool, onToggle: PropTypes.func, children: PropTypes.node, classBase: PropTypes.string } /** * The main menu entry component */ export class SidebarMenuItem extends React.Component { static propTypes = { // MenuContext props addEntry: PropTypes.func, updateEntry: PropTypes.func, removeEntry: PropTypes.func, entries: PropTypes.object, // Provided props parentId: PropTypes.string, children: PropTypes.node, isSubNode: PropTypes.bool, currentUrl: PropTypes.string, slim: PropTypes.bool, // User props icon: PropTypes.node, title: PropTypes.oneOfType([ PropTypes.string, PropTypes.node ]), to: PropTypes.string, href: PropTypes.string, exact: PropTypes.bool, noCaret: PropTypes.bool, } static defaultProps = { exact: true } constructor(props) { super(props); this.id = uuid(); } componentDidMount() { const entry = { id: this.id, parentId: this.props.parentId, exact: !!this.props.exact }; if (this.props.to) { entry.url = this.props.to; } this.props.addEntry(entry); } componentWillUnmount() { this.props.removeEntry(this.id); } getEntry() { return this.props.entries[this.id]; } toggleNode() { const entry = this.getEntry(); this.props.updateEntry(this.id, { open: !entry.open }); } render() { const entry = this.getEntry(); const classBase = this.props.isSubNode ? "sidebar-submenu" : "sidebar-menu"; const itemClass = classNames(`${classBase}__entry`, { [`${classBase}__entry--nested`]: !!this.props.children, 'open': entry && entry.open, 'active': entry && entry.active }); return (
  • { this.props.icon && React.cloneElement(this.props.icon, { className: classNames( this.props.icon.props.className, `${classBase}__entry__icon` ) }) } { typeof this.props.title === 'string' ? { this.props.title } : this.props.title } { this.props.children && ( ) }
  • ); } }