65 lines
2.0 KiB
React
65 lines
2.0 KiB
React
import React, { useState, useRef, useEffect } from 'react';
|
||
import './Dropdown.css';
|
||
|
||
/**
|
||
* Aurora Admin Dropdown(React)
|
||
* 对齐 组件2.txt Dropdown 规范:触发器点击展开、菜单项高32px、内边距左右12px、悬停 #F5F7FA、危险项 #F5222D、面板圆角6px/阴影中/最小宽120px
|
||
* items: [{ key, label, danger?, disabled?, divider?, icon? }]
|
||
*/
|
||
export default function Dropdown({ items = [], trigger = '操作', onSelect }) {
|
||
const [open, setOpen] = useState(false);
|
||
const rootRef = useRef(null);
|
||
|
||
useEffect(() => {
|
||
function onDocClick(e) {
|
||
if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
|
||
}
|
||
document.addEventListener('click', onDocClick);
|
||
return () => document.removeEventListener('click', onDocClick);
|
||
}, []);
|
||
|
||
const handleClick = (item) => {
|
||
if (item.disabled || item.divider) return;
|
||
onSelect && onSelect(item.key != null ? item.key : item.label);
|
||
setOpen(false);
|
||
};
|
||
|
||
return (
|
||
<div className="aa-dropdown" ref={rootRef}>
|
||
<div className="aa-dropdown-trigger" onClick={() => setOpen((o) => !o)}>
|
||
{trigger}
|
||
</div>
|
||
{open && (
|
||
<div className="aa-dropdown-panel">
|
||
{items.map((item, i) =>
|
||
item.divider ? (
|
||
<div key={`d${i}`} className="aa-dropdown-divider" />
|
||
) : (
|
||
<div
|
||
key={item.key || i}
|
||
className={`aa-dropdown-item${item.danger ? ' is-danger' : ''}${item.disabled ? ' is-disabled' : ''}`}
|
||
onClick={() => handleClick(item)}
|
||
>
|
||
{item.icon && <span className="ico">{item.icon}</span>}
|
||
{item.label}
|
||
</div>
|
||
)
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
/*
|
||
用法示例:
|
||
import Dropdown from './Dropdown';
|
||
const items = [
|
||
{ key: 'edit', label: '编辑' },
|
||
{ key: 'copy', label: '复制' },
|
||
{ divider: true },
|
||
{ key: 'delete', label: '删除', danger: true }
|
||
];
|
||
<Dropdown items={items} onSelect={(k) => console.log(k)} />
|
||
*/
|