Aurora Admin v1.2.0: 79 components x 5 ends, doc site, contracts batch 1, playground, regression, deploy ready
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import React, { useState } from 'react';
|
||||
import './SideMenu.css';
|
||||
|
||||
/**
|
||||
* Aurora Admin SideMenu(React)
|
||||
* 对齐 组件7.txt SideMenu 规范:多级、图标、徽章、选中态#F0F5FF+左指示条、折叠悬浮
|
||||
*
|
||||
* props:
|
||||
* - value / defaultValue : 当前选中 key
|
||||
* - items : [{ key, label, icon?, badge?, children?, disabled? }]
|
||||
* - collapsed
|
||||
* - onSelect(key)
|
||||
*/
|
||||
export default function SideMenu({ value, defaultValue = '', items = [], collapsed = false, onSelect }) {
|
||||
const [active, setActive] = useState(value !== undefined ? value : defaultValue);
|
||||
const [openKeys, setOpenKeys] = useState([]);
|
||||
const [hoverKey, setHoverKey] = useState('');
|
||||
const [popTop, setPopTop] = useState(0);
|
||||
const current = value !== undefined ? value : active;
|
||||
|
||||
const select = (key) => { if (value === undefined) setActive(key); onSelect && onSelect(key); setHoverKey(''); };
|
||||
const onTopClick = (it) => {
|
||||
if (it.disabled) return;
|
||||
if (it.children && it.children.length) {
|
||||
if (collapsed) return;
|
||||
setOpenKeys(openKeys.includes(it.key) ? openKeys.filter(k => k !== it.key) : [...openKeys, it.key]);
|
||||
} else select(it.key);
|
||||
};
|
||||
const onHover = (it, e) => { if (collapsed && it.children) { setHoverKey(it.key); setPopTop(e.currentTarget.offsetTop); } };
|
||||
const popItem = items.find(x => x.key === hoverKey) || null;
|
||||
|
||||
return (
|
||||
<div className={`aa-sidemenu${collapsed ? ' collapsed' : ''}`} onMouseLeave={() => setHoverKey('')}>
|
||||
{items.map(it => {
|
||||
const hasChild = it.children && it.children.length;
|
||||
const isOpen = openKeys.includes(it.key);
|
||||
return (
|
||||
<div key={it.key}>
|
||||
<div
|
||||
className={`aa-menu-item${current === it.key ? ' is-active' : ''}${it.disabled ? ' is-disabled' : ''}${hasChild && isOpen ? ' is-open' : ''}`}
|
||||
onClick={() => onTopClick(it)}
|
||||
onMouseEnter={(e) => onHover(it, e)}
|
||||
>
|
||||
<span className="aa-menu-icon">{it.icon}</span>
|
||||
<span className="aa-menu-label">{it.label}</span>
|
||||
{it.badge && <span className="aa-menu-badge">{it.badge}</span>}
|
||||
{hasChild && <span className="aa-menu-arrow">›</span>}
|
||||
</div>
|
||||
{hasChild && isOpen && !collapsed && (
|
||||
<div className="aa-menu-children">
|
||||
{it.children.map(c => (
|
||||
<div key={c.key} className={`aa-menu-item${current === c.key ? ' is-active' : ''}`} onClick={() => select(c.key)}>
|
||||
<span className="aa-menu-label">{c.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{collapsed && hoverKey && popItem && (
|
||||
<div className="aa-menu-pop" style={{ top: popTop }}>
|
||||
<div className="aa-menu-pop-title">{popItem.label}</div>
|
||||
{popItem.children && popItem.children.length ? (
|
||||
popItem.children.map(c => (
|
||||
<div key={c.key} className={`aa-menu-item${current === c.key ? ' is-active' : ''}`} onClick={() => select(c.key)}>
|
||||
<span className="aa-menu-label">{c.label}</span>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="aa-menu-item is-active" onClick={() => select(popItem.key)}>
|
||||
<span className="aa-menu-label">{popItem.label}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
用法示例:
|
||||
import SideMenu from './SideMenu';
|
||||
const items = [
|
||||
{ key: 'dashboard', label: '仪表盘', icon: '▦' },
|
||||
{ key: 'user', label: '用户管理', icon: '◍', badge: 8, children: [{ key: 'list', label: '用户列表' }] }
|
||||
];
|
||||
<SideMenu items={items} defaultValue="list" collapsed={false} onSelect={setActive} />
|
||||
*/
|
||||
Reference in New Issue
Block a user