import React, { useEffect, useRef, useState } from 'react'; import classnames from 'classnames-es-ts'; import Tooltip from 'antd/es/tooltip'; import { EngineInterface, formatHotkey, isMobile } from '@aomao/engine'; import { autoGetHotkey } from '../utils'; import 'antd/es/tooltip/style/css'; export type DropdownListItem = { key: string; icon?: React.ReactNode; content?: React.ReactNode | ((engine?: EngineInterface) => React.ReactNode); hotkey?: boolean | string; isDefault?: boolean; title?: string; placement?: | 'right' | 'top' | 'left' | 'bottom' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom'; className?: string; disabled?: boolean; command?: { name: string; args: Array } | Array; autoExecute?: boolean; }; export type DropdownListProps = { engine?: EngineInterface; direction?: 'vertical' | 'horizontal'; name: string; items: Array; values: string | Array; className?: string; onSelect?: (event: React.MouseEvent, key: string) => void | boolean; hasDot?: boolean; }; const DropdownList: React.FC = ({ engine, name, direction, items, className, onSelect, values, hasDot, }) => { if (!direction) direction = 'vertical'; const element = useRef(null); const [placement, setPlacement] = useState<'bottom' | 'top'>(); useEffect(() => { const current = element.current; if (!current) return; const scrollElement = engine?.scrollNode?.get(); if (!scrollElement) return; const rect = current.getBoundingClientRect(); const scrollRect = scrollElement.getBoundingClientRect(); if (rect.top < scrollRect.top) setPlacement('bottom'); if (rect.bottom > scrollRect.bottom) setPlacement('top'); }, [element]); const triggerSelect = (event: React.MouseEvent, key: string) => { event.preventDefault(); event.stopPropagation(); const item = items.find((item) => item.key === key); if (!item) return; const { autoExecute, command } = item; if (onSelect && onSelect(event, key) === false) return; if (autoExecute !== false) { let commandName = name; let commandArgs = [key]; if (command) { if (!Array.isArray(command)) { commandName = command.name; commandArgs = commandArgs.concat(command.args); } else { commandArgs = commandArgs.concat(command); } } engine?.command.execute(commandName, ...commandArgs); } }; const renderItem = ({ key, title, icon, content, command, placement, className, hotkey, disabled, }: DropdownListItem) => { const renderContent = () => ( { if (disabled) return; return triggerSelect(event, key); }} > {((typeof values === 'string' && values === key) || (Array.isArray(values) && values.indexOf(key) > -1)) && direction !== 'horizontal' && hasDot !== false && ( )} {typeof icon === 'string' ? ( ) : ( icon )} {typeof content === 'function' ? content(engine) : content} ); let titleElement = title ? (
{title}
) : null; //默认获取插件的热键 if (engine && hotkey !== false) { hotkey = autoGetHotkey( engine, command && !Array.isArray(command) ? command.name : name, key, ); } if (typeof hotkey === 'string' && hotkey !== '') { titleElement = ( <> {title}
{formatHotkey(hotkey)}
); } return titleElement && !isMobile ? ( {renderContent()} ) : ( renderContent() ); }; return (
{items.map((item) => renderItem(item))}
); }; export default DropdownList;