Aurora Admin v1.2.0: 79 components x 5 ends, doc site, contracts batch 1, playground, regression, deploy ready

This commit is contained in:
aurora-admin
2026-09-10 19:21:56 +08:00
commit 51ce3a28f7
654 changed files with 49082 additions and 0 deletions
+90
View File
@@ -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} />
*/