rc-menu@7.4.29

menu ui component for react

/* eslint no-console:0 */
import * as React from 'react';
import ReactDOM from 'react-dom';
import Menu, { SubMenu, Item as MenuItem, Divider } from 'rc-menu';
import 'rc-menu/assets/index.css';
import animate from 'css-animation';

const getSvgIcon = (style = {}, text) => {
  if (text) {
    return (
      <i style={style}>
        {text}
      </i>
    );
  }
  const path = 'M869 487.8L491.2 159.9c-2.9-2.5-6.6-3.9-10.5-3.9h' +
    '-88.5c-7.4 0-10.8 9.2-5.2 14l350.2 304H152c-4.4 0-8 3.6-8 8v' +
    '60c0 4.4 3.6 8 8 8h585.1L386.9 854c-5.6 4.9-2.2 14 5.2 14h91' +
    '.5c1.9 0 3.8-0.7 5.2-2L869 536.2c14.7-12.8 14.7-35.6 0-48.4z';
  return (
    <i style={style}>
      <svg
        viewBox="0 0 1024 1024"
        width="1em"
        height="1em"
        fill="currentColor"
        style={{ verticalAlign: '-.125em' }}
      >
        <path d={path} />
      </svg>
    </i>
  );
};

function itemIcon(props) {
  return getSvgIcon({
    position: 'absolute',
    right: '1rem',
    color: props.isSelected ? 'pink' : 'inherit',
  });
}

function expandIcon(props) {
  return getSvgIcon({
    position: 'absolute',
    right: '1rem',
    color: 'lightblue',
    transform: `rotate(${props.isOpen ? 90 : 0}deg)`,
  });
}

const animation = {
  enter(node, done) {
    let height;
    return animate(node, 'rc-menu-collapse', {
      start() {
        height = node.offsetHeight;
        node.style.height = 0;
      },
      active() {
        node.style.height = `${height}px`;
      },
      end() {
        node.style.height = '';
        done();
      },
    });
  },

  appear() {
    return this.enter.apply(this, arguments);
  },

  leave(node, done) {
    return animate(node, 'rc-menu-collapse', {
      start() {
        node.style.height = `${node.offsetHeight}px`;
      },
      active() {
        node.style.height = 0;
      },
      end() {
        node.style.height = '';
        done();
      },
    });
  },
};

class Demo extends React.Component {

  onOpenChange = (value) => {
    console.log('onOpenChange', value);
  }

  handleClick = (info) => {
    console.log(`clicked ${info.key}`);
    console.log(info);
  }

  renderNestSubMenu = (props = {}) => {
    return (
      <SubMenu title={<span>offset sub menu 2</span>} key="4" popupOffset={[10, 15]} {...props}>
        <MenuItem key="4-1">inner inner</MenuItem>
        <Divider />
        <SubMenu
          key="4-2"
          title={<span>sub menu 3</span>}
        >
          <SubMenu title="sub 4-2-0" key="4-2-0">
            <MenuItem key="4-2-0-1">inner inner</MenuItem>
            <MenuItem key="4-2-0-2">inner inner2</MenuItem>
          </SubMenu>
          <MenuItem key="4-2-1">inn</MenuItem>
          <SubMenu title={<span>sub menu 4</span>} key="4-2-2">
            <MenuItem key="4-2-2-1">inner inner</MenuItem>
            <MenuItem key="4-2-2-2">inner inner2</MenuItem>
          </SubMenu>
          <SubMenu title="sub 4-2-3" key="4-2-3">
            <MenuItem key="4-2-3-1">inner inner</MenuItem>
            <MenuItem key="4-2-3-2">inner inner2</MenuItem>
          </SubMenu>
        </SubMenu>
      </SubMenu>
    );
  }

  renderCommonMenu = (props = {}) => {
    return (
      <Menu onClick={this.handleClick} onOpenChange={this.onOpenChange} {...props}>
        <SubMenu title={<span>sub menu</span>} key="1">
          <MenuItem key="1-1">0-1</MenuItem>
          <MenuItem key="1-2">0-2</MenuItem>
        </SubMenu>
        {this.renderNestSubMenu()}
        <MenuItem key="2">1</MenuItem>
        <MenuItem key="3">outer</MenuItem>
        <MenuItem disabled>disabled</MenuItem>
        <MenuItem key="5">outer3</MenuItem>
      </Menu>
    );
  }

  render() {
    const verticalMenu = this.renderCommonMenu({
      mode: 'vertical',
      openAnimation: 'zoom',
      itemIcon,
      expandIcon,
    });

    const inlineMenu = this.renderCommonMenu({
      mode: 'inline',
      defaultOpenKeys: ['1'],
      openAnimation: animation,
      itemIcon,
      expandIcon,
    });

    return (
      <div style={{ margin: 20 }}>
        <h2>Antd menu - Custom icon</h2>
        <div>
          <h3>vertical</h3>
          <div style={{ margin: 20, width: 200 }}>{verticalMenu}</div>
          <h3>inline</h3>
          <div style={{ margin: 20, width: 400 }}>{inlineMenu}</div>
        </div>
      </div>
    );
  }
}

ReactDOM.render(<Demo />, document.getElementById('__react-content'));
Fork me on GitHub