119 lines
4.2 KiB
JavaScript
119 lines
4.2 KiB
JavaScript
import React, { useState } from 'react';
|
|
import { NavLink } from 'react-router-dom';
|
|
import { CSSTransition } from 'react-transition-group';
|
|
import classNames from 'classnames';
|
|
import {Ripple} from "primereact/ripple";
|
|
import { Badge } from 'primereact/badge';
|
|
|
|
const AppSubmenu = (props) => {
|
|
|
|
const [activeIndex, setActiveIndex] = useState(null)
|
|
|
|
const onMenuItemClick = (event, item, index) => {
|
|
//avoid processing disabled items
|
|
if (item.disabled) {
|
|
event.preventDefault();
|
|
return true;
|
|
}
|
|
|
|
//execute command
|
|
if (item.command) {
|
|
item.command({ originalEvent: event, item: item });
|
|
}
|
|
|
|
if (index === activeIndex)
|
|
setActiveIndex(null);
|
|
else
|
|
setActiveIndex(index);
|
|
|
|
if (props.onMenuItemClick) {
|
|
props.onMenuItemClick({
|
|
originalEvent: event,
|
|
item: item
|
|
});
|
|
}
|
|
}
|
|
|
|
const onKeyDown = (event) => {
|
|
if (event.code === 'Enter' || event.code === 'Space'){
|
|
event.preventDefault();
|
|
event.target.click();
|
|
}
|
|
}
|
|
|
|
const renderLinkContent = (item) => {
|
|
let submenuIcon = item.items && <i className="pi pi-fw pi-angle-down menuitem-toggle-icon"></i>;
|
|
let badge = item.badge && <Badge value={item.badge} />
|
|
|
|
return (
|
|
<React.Fragment>
|
|
<i className={item.icon}></i>
|
|
<span>{item.label}</span>
|
|
{submenuIcon}
|
|
{badge}
|
|
<Ripple/>
|
|
</React.Fragment>
|
|
);
|
|
}
|
|
|
|
const renderLink = (item, i) => {
|
|
let content = renderLinkContent(item);
|
|
|
|
if (item.to) {
|
|
return (
|
|
<NavLink aria-label={item.label} onKeyDown={onKeyDown} role="menuitem" className="p-ripple" activeClassName="router-link-active router-link-exact-active" to={item.to} onClick={(e) => onMenuItemClick(e, item, i)} exact target={item.target}>
|
|
{content}
|
|
</NavLink>
|
|
)
|
|
}
|
|
else {
|
|
return (
|
|
<a tabIndex="0" aria-label={item.label} onKeyDown={onKeyDown} role="menuitem" href={item.url} className="p-ripple" onClick={(e) => onMenuItemClick(e, item, i)} target={item.target}>
|
|
{content}
|
|
</a>
|
|
);
|
|
}
|
|
}
|
|
|
|
let items = props.items && props.items.map((item, i) => {
|
|
let active = activeIndex === i;
|
|
let styleClass = classNames(item.badgeStyleClass, {'layout-menuitem-category': props.root, 'active-menuitem': active && !item.to });
|
|
|
|
if(props.root) {
|
|
return (
|
|
<li className={styleClass} key={i} role="none">
|
|
{props.root === true && <React.Fragment>
|
|
<div className="layout-menuitem-root-text" aria-label={item.label}>{item.label}</div>
|
|
<AppSubmenu items={item.items} onMenuItemClick={props.onMenuItemClick} />
|
|
</React.Fragment>}
|
|
</li>
|
|
);
|
|
}
|
|
else {
|
|
return (
|
|
<li className={styleClass} key={i} role="none">
|
|
{renderLink(item, i)}
|
|
<CSSTransition classNames="layout-submenu-wrapper" timeout={{ enter: 1000, exit: 450 }} in={active} unmountOnExit>
|
|
<AppSubmenu items={item.items} onMenuItemClick={props.onMenuItemClick} />
|
|
</CSSTransition>
|
|
</li>
|
|
);
|
|
}
|
|
});
|
|
|
|
return items ? <ul className={props.className} role="menu">{items}</ul> : null;
|
|
}
|
|
|
|
export const AppMenu = (props) => {
|
|
|
|
return (
|
|
<div className="layout-menu-container">
|
|
<AppSubmenu items={props.model} className="layout-menu" onMenuItemClick={props.onMenuItemClick} root={true} role="menu" />
|
|
<a href="https://www.primefaces.org/primeblocks-react" className="block mt-3">
|
|
<img alt="primeblocks" className="w-full"
|
|
src={props.layoutColorMode === 'light' ? 'assets/layout/images/banner-primeblocks.png' : 'assets/layout/images/banner-primeblocks-dark.png'}/>
|
|
</a>
|
|
</div>
|
|
);
|
|
}
|