Web: Components: ContextMenu: Refactoring
This commit is contained in:
parent
56ecbc95ea
commit
c10944f8fa
@ -1,266 +1,11 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import DomHelpers from "../utils/domHelpers";
|
||||
import ObjectUtils from "../utils/objectUtils";
|
||||
import { classNames } from "../utils/classNames";
|
||||
import { CSSTransition } from "react-transition-group";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import Portal from "../portal";
|
||||
import StyledContextMenu from "./styled-context-menu";
|
||||
import ArrowIcon from "./svg/arrow.right.react.svg";
|
||||
|
||||
class ContextMenuSub extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
activeItem: null,
|
||||
};
|
||||
|
||||
this.onEnter = this.onEnter.bind(this);
|
||||
|
||||
this.submenuRef = React.createRef();
|
||||
}
|
||||
|
||||
onItemMouseEnter(e, item) {
|
||||
if (item.disabled) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
activeItem: item,
|
||||
});
|
||||
}
|
||||
|
||||
onItemClick(item, e) {
|
||||
if (item.disabled) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.url) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (item.onClick) {
|
||||
item.onClick({
|
||||
originalEvent: e,
|
||||
action: item.action,
|
||||
});
|
||||
}
|
||||
|
||||
if (!item.items) {
|
||||
this.props.onLeafClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
position() {
|
||||
const parentItem = this.submenuRef.current.parentElement;
|
||||
const containerOffset = DomHelpers.getOffset(
|
||||
this.submenuRef.current.parentElement
|
||||
);
|
||||
const viewport = DomHelpers.getViewport();
|
||||
const sublistWidth = this.submenuRef.current.offsetParent
|
||||
? this.submenuRef.current.offsetWidth
|
||||
: DomHelpers.getHiddenElementOuterWidth(this.submenuRef.current);
|
||||
const itemOuterWidth = DomHelpers.getOuterWidth(parentItem.children[0]);
|
||||
|
||||
this.submenuRef.current.style.top = "0px";
|
||||
|
||||
if (
|
||||
parseInt(containerOffset.left, 10) + itemOuterWidth + sublistWidth >
|
||||
viewport.width - DomHelpers.calculateScrollbarWidth()
|
||||
) {
|
||||
this.submenuRef.current.style.left = -1 * sublistWidth + "px";
|
||||
} else {
|
||||
this.submenuRef.current.style.left = itemOuterWidth + "px";
|
||||
}
|
||||
}
|
||||
|
||||
onEnter() {
|
||||
this.position();
|
||||
}
|
||||
|
||||
isActive() {
|
||||
return this.props.root || !this.props.resetMenu;
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (nextProps.resetMenu === true) {
|
||||
return {
|
||||
activeItem: null,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.isActive()) {
|
||||
this.position();
|
||||
}
|
||||
}
|
||||
|
||||
renderSeparator(index) {
|
||||
return (
|
||||
<li
|
||||
key={"separator_" + index}
|
||||
className="p-menu-separator not-selectable"
|
||||
role="separator"
|
||||
></li>
|
||||
);
|
||||
}
|
||||
|
||||
renderSubmenu(item) {
|
||||
if (item.items) {
|
||||
return (
|
||||
<ContextMenuSub
|
||||
model={item.items}
|
||||
resetMenu={item !== this.state.activeItem}
|
||||
onLeafClick={this.props.onLeafClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
renderMenuitem(item, index) {
|
||||
if (item.disabled) return; //TODO: Not render disabled items
|
||||
const active = this.state.activeItem === item;
|
||||
const className = classNames(
|
||||
"p-menuitem",
|
||||
{ "p-menuitem-active": active },
|
||||
item.className
|
||||
);
|
||||
const linkClassName = classNames("p-menuitem-link", "not-selectable", {
|
||||
"p-disabled": item.disabled,
|
||||
});
|
||||
const iconClassName = classNames("p-menuitem-icon", {
|
||||
"p-disabled": item.disabled,
|
||||
});
|
||||
const submenuIconClassName = "p-submenu-icon";
|
||||
const icon = item.icon && (
|
||||
<ReactSVG
|
||||
wrapper="span"
|
||||
className={iconClassName}
|
||||
src={item.icon}
|
||||
></ReactSVG>
|
||||
);
|
||||
const label = item.label && (
|
||||
<span className="p-menuitem-text not-selectable">{item.label}</span>
|
||||
);
|
||||
const submenuIcon = item.items && (
|
||||
<ArrowIcon className={submenuIconClassName} />
|
||||
);
|
||||
const submenu = this.renderSubmenu(item);
|
||||
const dataKeys = Object.fromEntries(
|
||||
Object.entries(item).filter((el) => el[0].indexOf("data-") === 0)
|
||||
);
|
||||
const onClick = (e) => {
|
||||
this.onItemClick(item, e);
|
||||
};
|
||||
let content = (
|
||||
<a
|
||||
href={item.url || "#"}
|
||||
className={linkClassName}
|
||||
target={item.target}
|
||||
{...dataKeys}
|
||||
onClick={onClick}
|
||||
role="menuitem"
|
||||
>
|
||||
{icon}
|
||||
{label}
|
||||
{submenuIcon}
|
||||
</a>
|
||||
);
|
||||
|
||||
if (item.template) {
|
||||
const defaultContentOptions = {
|
||||
onClick,
|
||||
className: linkClassName,
|
||||
labelClassName: "p-menuitem-text",
|
||||
iconClassName,
|
||||
submenuIconClassName,
|
||||
element: content,
|
||||
props: this.props,
|
||||
active,
|
||||
};
|
||||
|
||||
content = ObjectUtils.getJSXElement(
|
||||
item.template,
|
||||
item,
|
||||
defaultContentOptions
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
key={item.label + "_" + index}
|
||||
role="none"
|
||||
className={className}
|
||||
style={item.style}
|
||||
onMouseEnter={(event) => this.onItemMouseEnter(event, item)}
|
||||
>
|
||||
{content}
|
||||
{submenu}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
renderItem(item, index) {
|
||||
if (!item) return null;
|
||||
if (item.isSeparator) return this.renderSeparator(index);
|
||||
else return this.renderMenuitem(item, index);
|
||||
}
|
||||
|
||||
renderMenu() {
|
||||
if (this.props.model) {
|
||||
return this.props.model.map((item, index) => {
|
||||
return this.renderItem(item, index);
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const className = classNames({ "p-submenu-list": !this.props.root });
|
||||
const submenu = this.renderMenu();
|
||||
const isActive = this.isActive();
|
||||
|
||||
return (
|
||||
<CSSTransition
|
||||
nodeRef={this.submenuRef}
|
||||
classNames="p-contextmenusub"
|
||||
in={isActive}
|
||||
timeout={{ enter: 0, exit: 0 }}
|
||||
unmountOnExit={true}
|
||||
onEnter={this.onEnter}
|
||||
>
|
||||
<ul ref={this.submenuRef} className={`${className} not-selectable`}>
|
||||
{submenu}
|
||||
</ul>
|
||||
</CSSTransition>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ContextMenuSub.propTypes = {
|
||||
model: PropTypes.any,
|
||||
root: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
resetMenu: PropTypes.bool,
|
||||
onLeafClick: PropTypes.func,
|
||||
};
|
||||
|
||||
ContextMenuSub.defaultProps = {
|
||||
model: null,
|
||||
root: false,
|
||||
className: null,
|
||||
resetMenu: false,
|
||||
onLeafClick: null,
|
||||
};
|
||||
import SubMenu from "./sub-components/sub-menu";
|
||||
|
||||
class ContextMenu extends Component {
|
||||
constructor(props) {
|
||||
@ -272,34 +17,22 @@ class ContextMenu extends Component {
|
||||
resetMenu: false,
|
||||
};
|
||||
|
||||
this.onMenuClick = this.onMenuClick.bind(this);
|
||||
this.onLeafClick = this.onLeafClick.bind(this);
|
||||
this.onMenuMouseEnter = this.onMenuMouseEnter.bind(this);
|
||||
this.onEnter = this.onEnter.bind(this);
|
||||
this.onEntered = this.onEntered.bind(this);
|
||||
this.onExit = this.onExit.bind(this);
|
||||
this.onExited = this.onExited.bind(this);
|
||||
|
||||
this.menuRef = React.createRef();
|
||||
}
|
||||
|
||||
onMenuClick() {
|
||||
onMenuClick = () => {
|
||||
this.setState({
|
||||
resetMenu: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMenuMouseEnter() {
|
||||
onMenuMouseEnter = () => {
|
||||
this.setState({
|
||||
resetMenu: false,
|
||||
});
|
||||
}
|
||||
|
||||
show(e) {
|
||||
if (!(e instanceof Event)) {
|
||||
e.persist();
|
||||
}
|
||||
};
|
||||
|
||||
show = (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
@ -314,7 +47,7 @@ class ContextMenu extends Component {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.state.visible && prevState.reshow !== this.state.reshow) {
|
||||
@ -323,7 +56,6 @@ class ContextMenu extends Component {
|
||||
{
|
||||
visible: false,
|
||||
reshow: false,
|
||||
rePosition: false,
|
||||
resetMenu: true,
|
||||
},
|
||||
() => this.show(event)
|
||||
@ -331,20 +63,16 @@ class ContextMenu extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
hide(e) {
|
||||
if (!(e instanceof Event)) {
|
||||
e.persist();
|
||||
}
|
||||
|
||||
hide = (e) => {
|
||||
this.currentEvent = e;
|
||||
this.setState({ visible: false, reshow: false }, () => {
|
||||
if (this.props.onHide) {
|
||||
this.props.onHide(this.currentEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onEnter() {
|
||||
onEnter = () => {
|
||||
if (this.props.autoZIndex) {
|
||||
this.menuRef.current.style.zIndex = String(
|
||||
this.props.baseZIndex + DomHelpers.generateZIndex()
|
||||
@ -352,22 +80,22 @@ class ContextMenu extends Component {
|
||||
}
|
||||
|
||||
this.position(this.currentEvent);
|
||||
}
|
||||
};
|
||||
|
||||
onEntered() {
|
||||
onEntered = () => {
|
||||
this.bindDocumentListeners();
|
||||
}
|
||||
};
|
||||
|
||||
onExit() {
|
||||
onExit = () => {
|
||||
this.currentEvent = null;
|
||||
this.unbindDocumentListeners();
|
||||
}
|
||||
};
|
||||
|
||||
onExited() {
|
||||
onExited = () => {
|
||||
DomHelpers.revertZIndex();
|
||||
}
|
||||
};
|
||||
|
||||
position(event) {
|
||||
position = (event) => {
|
||||
if (event) {
|
||||
const rects = this.props.containerRef?.current.getBoundingClientRect();
|
||||
|
||||
@ -412,9 +140,9 @@ class ContextMenu extends Component {
|
||||
this.menuRef.current.style.left = left + "px";
|
||||
this.menuRef.current.style.top = top + "px";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onLeafClick(e) {
|
||||
onLeafClick = (e) => {
|
||||
this.setState({
|
||||
resetMenu: true,
|
||||
});
|
||||
@ -422,9 +150,9 @@ class ContextMenu extends Component {
|
||||
this.hide(e);
|
||||
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
isOutsideClicked(e) {
|
||||
isOutsideClicked = (e) => {
|
||||
return (
|
||||
this.menuRef &&
|
||||
this.menuRef.current &&
|
||||
@ -433,19 +161,19 @@ class ContextMenu extends Component {
|
||||
this.menuRef.current.contains(e.target)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
bindDocumentListeners() {
|
||||
bindDocumentListeners = () => {
|
||||
this.bindDocumentResizeListener();
|
||||
this.bindDocumentClickListener();
|
||||
}
|
||||
};
|
||||
|
||||
unbindDocumentListeners() {
|
||||
unbindDocumentListeners = () => {
|
||||
this.unbindDocumentResizeListener();
|
||||
this.unbindDocumentClickListener();
|
||||
}
|
||||
};
|
||||
|
||||
bindDocumentClickListener() {
|
||||
bindDocumentClickListener = () => {
|
||||
if (!this.documentClickListener) {
|
||||
this.documentClickListener = (e) => {
|
||||
if (this.isOutsideClicked(e)) {
|
||||
@ -461,9 +189,9 @@ class ContextMenu extends Component {
|
||||
document.addEventListener("click", this.documentClickListener);
|
||||
document.addEventListener("mousedown", this.documentClickListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bindDocumentContextMenuListener() {
|
||||
bindDocumentContextMenuListener = () => {
|
||||
if (!this.documentContextMenuListener) {
|
||||
this.documentContextMenuListener = (e) => {
|
||||
this.show(e);
|
||||
@ -474,9 +202,9 @@ class ContextMenu extends Component {
|
||||
this.documentContextMenuListener
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bindDocumentResizeListener() {
|
||||
bindDocumentResizeListener = () => {
|
||||
if (!this.documentResizeListener) {
|
||||
this.documentResizeListener = (e) => {
|
||||
if (this.state.visible) {
|
||||
@ -486,17 +214,17 @@ class ContextMenu extends Component {
|
||||
|
||||
window.addEventListener("resize", this.documentResizeListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unbindDocumentClickListener() {
|
||||
unbindDocumentClickListener = () => {
|
||||
if (this.documentClickListener) {
|
||||
document.removeEventListener("click", this.documentClickListener);
|
||||
document.removeEventListener("mousedown", this.documentClickListener);
|
||||
this.documentClickListener = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unbindDocumentContextMenuListener() {
|
||||
unbindDocumentContextMenuListener = () => {
|
||||
if (this.documentContextMenuListener) {
|
||||
document.removeEventListener(
|
||||
"contextmenu",
|
||||
@ -504,14 +232,14 @@ class ContextMenu extends Component {
|
||||
);
|
||||
this.documentContextMenuListener = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unbindDocumentResizeListener() {
|
||||
unbindDocumentResizeListener = () => {
|
||||
if (this.documentResizeListener) {
|
||||
window.removeEventListener("resize", this.documentResizeListener);
|
||||
this.documentResizeListener = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.global) {
|
||||
@ -526,7 +254,7 @@ class ContextMenu extends Component {
|
||||
DomHelpers.revertZIndex();
|
||||
}
|
||||
|
||||
renderContextMenu() {
|
||||
renderContextMenu = () => {
|
||||
const className = classNames(
|
||||
"p-contextmenu p-component",
|
||||
this.props.className
|
||||
@ -553,7 +281,7 @@ class ContextMenu extends Component {
|
||||
onClick={this.onMenuClick}
|
||||
onMouseEnter={this.onMenuMouseEnter}
|
||||
>
|
||||
<ContextMenuSub
|
||||
<SubMenu
|
||||
model={this.props.model}
|
||||
root
|
||||
resetMenu={this.state.resetMenu}
|
||||
@ -563,7 +291,7 @@ class ContextMenu extends Component {
|
||||
</CSSTransition>
|
||||
</StyledContextMenu>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const element = this.renderContextMenu();
|
||||
|
@ -0,0 +1,239 @@
|
||||
import React, { useRef, useState, useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import DomHelpers from "../../utils/domHelpers";
|
||||
import ObjectUtils from "../../utils/objectUtils";
|
||||
import { classNames } from "../../utils/classNames";
|
||||
import { CSSTransition } from "react-transition-group";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import ArrowIcon from "../svg/arrow.right.react.svg";
|
||||
|
||||
const SubMenu = (props) => {
|
||||
const { onLeafClick, root, resetMenu, model } = props;
|
||||
|
||||
const [activeItem, setActiveItem] = useState(null);
|
||||
const subMenuRef = useRef();
|
||||
|
||||
const onItemMouseEnter = (e, item) => {
|
||||
if (item.disabled) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
setActiveItem(item);
|
||||
};
|
||||
|
||||
const onItemClick = (e, item) => {
|
||||
const { disabled, url, onClick, items, action } = item;
|
||||
if (disabled) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (onClick) {
|
||||
onClick({
|
||||
originalEvent: e,
|
||||
action: action,
|
||||
});
|
||||
}
|
||||
|
||||
if (!items) {
|
||||
onLeafClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
const position = () => {
|
||||
const parentItem = subMenuRef.current.parentElement;
|
||||
const containerOffset = DomHelpers.getOffset(
|
||||
subMenuRef.current.parentElement
|
||||
);
|
||||
const viewport = DomHelpers.getViewport();
|
||||
const subListWidth = subMenuRef.current.offsetParent
|
||||
? subMenuRef.current.offsetWidth
|
||||
: DomHelpers.getHiddenElementOuterWidth(subMenuRef.current);
|
||||
const itemOuterWidth = DomHelpers.getOuterWidth(parentItem.children[0]);
|
||||
|
||||
subMenuRef.current.style.top = "0px";
|
||||
|
||||
if (
|
||||
parseInt(containerOffset.left, 10) + itemOuterWidth + subListWidth >
|
||||
viewport.width - DomHelpers.calculateScrollbarWidth()
|
||||
) {
|
||||
subMenuRef.current.style.left = -1 * subListWidth + "px";
|
||||
} else {
|
||||
subMenuRef.current.style.left = itemOuterWidth + "px";
|
||||
}
|
||||
};
|
||||
|
||||
const onEnter = () => {
|
||||
position();
|
||||
};
|
||||
|
||||
const isActive = () => {
|
||||
return root || !resetMenu;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isActive()) {
|
||||
position();
|
||||
}
|
||||
});
|
||||
|
||||
const renderSeparator = (index) => (
|
||||
<li
|
||||
key={"separator_" + index}
|
||||
className="p-menu-separator not-selectable"
|
||||
role="separator"
|
||||
></li>
|
||||
);
|
||||
|
||||
const renderSubMenu = (item) => {
|
||||
if (item.items) {
|
||||
return (
|
||||
<SubMenu
|
||||
model={item.items}
|
||||
resetMenu={item !== activeItem}
|
||||
onLeafClick={onLeafClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const renderMenuitem = (item, index) => {
|
||||
if (item.disabled) return;
|
||||
//TODO: Not render disabled items
|
||||
const active = activeItem === item;
|
||||
const className = classNames(
|
||||
"p-menuitem",
|
||||
{ "p-menuitem-active": active },
|
||||
item.className
|
||||
);
|
||||
const linkClassName = classNames("p-menuitem-link", "not-selectable", {
|
||||
"p-disabled": item.disabled,
|
||||
});
|
||||
const iconClassName = classNames("p-menuitem-icon", {
|
||||
"p-disabled": item.disabled,
|
||||
});
|
||||
const subMenuIconClassName = "p-submenu-icon";
|
||||
const icon = item.icon && (
|
||||
<ReactSVG wrapper="span" className={iconClassName} src={item.icon} />
|
||||
);
|
||||
const label = item.label && (
|
||||
<span className="p-menuitem-text not-selectable">{item.label}</span>
|
||||
);
|
||||
const subMenuIcon = item.items && (
|
||||
<ArrowIcon className={subMenuIconClassName} />
|
||||
);
|
||||
const subMenu = renderSubMenu(item);
|
||||
const dataKeys = Object.fromEntries(
|
||||
Object.entries(item).filter((el) => el[0].indexOf("data-") === 0)
|
||||
);
|
||||
const onClick = (e) => {
|
||||
onItemClick(e, item);
|
||||
};
|
||||
let content = (
|
||||
<a
|
||||
href={item.url || "#"}
|
||||
className={linkClassName}
|
||||
target={item.target}
|
||||
{...dataKeys}
|
||||
onClick={onClick}
|
||||
role="menuitem"
|
||||
>
|
||||
{icon}
|
||||
{label}
|
||||
{subMenuIcon}
|
||||
</a>
|
||||
);
|
||||
|
||||
if (item.template) {
|
||||
const defaultContentOptions = {
|
||||
onClick,
|
||||
className: linkClassName,
|
||||
labelClassName: "p-menuitem-text",
|
||||
iconClassName,
|
||||
subMenuIconClassName,
|
||||
element: content,
|
||||
props: props,
|
||||
active,
|
||||
};
|
||||
|
||||
content = ObjectUtils.getJSXElement(
|
||||
item.template,
|
||||
item,
|
||||
defaultContentOptions
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
key={item.label + "_" + index}
|
||||
role="none"
|
||||
className={className}
|
||||
style={item.style}
|
||||
onMouseEnter={(e) => onItemMouseEnter(e, item)}
|
||||
>
|
||||
{content}
|
||||
{subMenu}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const renderItem = (item, index) => {
|
||||
if (!item) return null;
|
||||
if (item.isSeparator) return renderSeparator(index);
|
||||
else return renderMenuitem(item, index);
|
||||
};
|
||||
|
||||
const renderMenu = () => {
|
||||
if (model) {
|
||||
return model.map((item, index) => {
|
||||
return renderItem(item, index);
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const className = classNames({ "p-submenu-list": !root });
|
||||
const submenu = renderMenu();
|
||||
const active = isActive();
|
||||
|
||||
return (
|
||||
<CSSTransition
|
||||
nodeRef={subMenuRef}
|
||||
classNames="p-contextmenusub"
|
||||
in={active}
|
||||
timeout={{ enter: 0, exit: 0 }}
|
||||
unmountOnExit={true}
|
||||
onEnter={onEnter}
|
||||
>
|
||||
<ul ref={subMenuRef} className={`${className} not-selectable`}>
|
||||
{submenu}
|
||||
</ul>
|
||||
</CSSTransition>
|
||||
);
|
||||
};
|
||||
|
||||
SubMenu.propTypes = {
|
||||
model: PropTypes.any,
|
||||
root: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
resetMenu: PropTypes.bool,
|
||||
onLeafClick: PropTypes.func,
|
||||
};
|
||||
|
||||
SubMenu.defaultProps = {
|
||||
model: null,
|
||||
root: false,
|
||||
className: null,
|
||||
resetMenu: false,
|
||||
onLeafClick: null,
|
||||
};
|
||||
|
||||
export default SubMenu;
|
Loading…
Reference in New Issue
Block a user