terra-menu
Version:
The menu is a popup component that displays a list of items, item groups, and dividers. Menu Items can be actionable, have toggle-style selection, or have nested submenu items. Menu Item groups are a single-select grouping of menu items. The Menu will det
83 lines (71 loc) • 2.41 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import List, { Utils } from 'terra-list';
const propTypes = {
/**
* Menu.Items to be grouped together.
*/
children: PropTypes.node.isRequired,
/**
* Callback function called when selected index changes.
*/
onChange: PropTypes.func,
};
const childContextTypes = {
isGroupItem: PropTypes.bool, shouldReserveSpaceForIcon: PropTypes.bool,
};
const initialSingleToggledIndex = (children) => {
const childArray = React.Children.toArray(children);
for (let i = 0; i < childArray.length; i += 1) {
if (childArray[i].props.isSelected || childArray[i].props.isToggled) {
return i;
}
}
return -1;
};
class MenuItemGroup extends React.Component {
constructor(props) {
super(props);
this.cloneChildren = this.cloneChildren.bind(this);
this.handleItemToggled = this.handleItemToggled.bind(this);
this.state = { toggledIndex: initialSingleToggledIndex(props.children) };
}
getChildContext() {
return { isGroupItem: true, shouldReserveSpaceForIcon: true };
}
handleItemToggled(event, metaData) {
if (this.state.toggledIndex !== metaData.index && !metaData.isDisabled) {
event.preventDefault();
this.setState({ toggledIndex: metaData.index });
if (this.props.onChange) {
this.props.onChange(event, metaData.index);
}
}
}
cloneChildren(children) {
return React.Children.map(children, (child, index) => {
let isToggleable = true;
if (child.props.isToggleable === false && child.props.isSelectable === false) {
isToggleable = false;
}
return React.cloneElement(child, {
isToggleable,
isToggled: this.state.toggledIndex === index,
onClick: Utils.wrappedOnClickForItem(child.props.onClick, this.handleItemToggled, { index, isDisabled: child.props.isDisabled }),
onKeyDown: Utils.wrappedOnKeyDownForItem(child.props.onKeyDown, this.handleItemToggled, { index, isDisabled: child.props.isDisabled }),
});
});
}
render() {
const { children, ...customProps } = this.props;
const managedChildren = this.cloneChildren(children);
return (
<List {...customProps} role="group">
{managedChildren}
</List>
);
}
}
MenuItemGroup.propTypes = propTypes;
MenuItemGroup.childContextTypes = childContextTypes;
export default MenuItemGroup;