fix(menu): refactor menu system to use pure config objects and fix submenu click events

This commit is contained in:
yuding
2025-12-09 18:34:43 +08:00
parent c112c87dad
commit 9ae1d9d809
38 changed files with 6756 additions and 2575 deletions

201
dist/index.d.ts vendored
View File

@@ -146,6 +146,7 @@ export declare class BimEngine extends EventEmitter {
buttonGroup: ButtonGroupManager | null;
dialog: DialogManager | null;
engine: EngineManager | null;
rightKey: RightKeyManager | null;
get localeManager(): LocaleManager;
get themeManager(): ThemeManager;
constructor(container: HTMLElement | string, options?: {
@@ -169,6 +170,111 @@ export declare class BimEngine extends EventEmitter {
destroy(): void;
}
/**
* 通用菜单列表组件
* 负责渲染一组菜单项,支持分组、排序、图标、快捷键提示和递归多级子菜单。
* 它不包含定位逻辑,仅负责内容渲染。
*/
export declare class BimMenu implements IBimComponent {
element: HTMLElement;
private options;
private unsubscribeLocale;
private unsubscribeTheme;
private activeSubMenu;
constructor(options: MenuOptions);
/**
* 初始化组件
* 渲染 DOM 结构并订阅语言变更
*/
init(): void;
/**
* 设置主题
* @param theme 全局主题配置
*/
setTheme(theme: ThemeConfig): void;
/**
* 响应语言变更
* 重新渲染整个菜单以更新文本
*/
setLocales(): void;
/**
* 销毁组件
* 清理事件监听、子菜单和 DOM 元素
*/
destroy(): void;
/**
* 获取组件根元素
* 实现 IRightKeyContent 接口,允许被 RightKey 容器挂载
*/
getElement(): HTMLElement;
/**
* 核心渲染逻辑
* 处理分组、排序和 DOM 生成
*/
private render;
/**
* 创建单个菜单项的 DOM 元素
*/
private createItemElement;
/**
* 打开子菜单
* @param item 当前菜单项
* @param parentLi 触发的 DOM 元素(用于定位)
*/
private openSubMenu;
/**
* 关闭当前激活的子菜单
*/
private closeSubMenu;
}
/**
* 右键浮层容器组件 (RightKey)
* 这是一个纯粹的定位容器,负责在屏幕指定位置显示内容。
* 它不关心具体内容是什么,只处理定位、边界检测和关闭逻辑。
*/
export declare class BimRightKey implements IBimComponent {
private element;
private content;
private isVisible;
private onCloseCallback?;
constructor(options?: RightKeyOptions);
init(): void;
setTheme(_theme: ThemeConfig): void;
setLocales(): void;
destroy(): void;
/**
* 设置关闭时的回调函数
* 通常用于通知 Manager 状态变更
*/
setOnClose(callback: () => void): void;
/**
* 挂载内容组件
* @param content 实现了 IRightKeyContent 接口的组件实例
*/
mount(content: IRightKeyContent): void;
/**
* 卸载当前内容
*/
unmountContent(): void;
/**
* 在指定位置显示容器
* 包含智能边界检测逻辑,防止溢出屏幕
* @param x 目标 X 坐标 (通常是鼠标点击位置)
* @param y 目标 Y 坐标
*/
show(x: number, y: number): void;
/**
* 隐藏容器
*/
hide(): void;
/**
* 处理全局点击事件
* 用于检测是否点击了容器外部
*/
private handleGlobalClick;
}
/** 按钮内部文字图标排列 */
declare type ButtonAlign = 'vertical' | 'horizontal';
@@ -249,11 +355,11 @@ export declare function createEngine(r) {
const e = r.version || "v1";
switch (e) {
case "v2":
return new Nc(r);
return new Bc(r);
case "v1":
return new I_(r);
return new N_(r);
:
return console.warn(`Version '${e}' not found. Falling back to v2.`), new Nc(r);
return console.warn(`Version '${e}' not found. Falling back to v2.`), new Bc(r);
}
}
@@ -483,6 +589,17 @@ declare interface IBimComponent {
destroy(): void;
}
declare interface IRightKeyContent {
/**
* 获取组件的根 DOM 元素
*/
getElement(): HTMLElement;
/**
* 销毁组件
*/
destroy(): void;
}
declare type Listener<T = any> = (payload: T) => void;
declare type LocaleChangeListener = (locale: LocaleType) => void;
@@ -519,6 +636,39 @@ declare class LocaleManager {
*/
declare type LocaleType = 'zh-CN' | 'en-US';
/**
* 菜单项配置接口 (用于简化的对象配置)
*/
export declare interface MenuItemConfig {
id: string;
label: string;
onClick?: () => void;
icon?: string;
group?: string;
order?: number;
children?: MenuItemConfig[];
disabled?: boolean;
visible?: boolean;
}
/**
* <20><><EFBFBD>单组件配置选项
*/
declare interface MenuOptions {
/**
* 菜单项列表
* 可以是扁平数组,组件会根据 group 字段自动分组
*/
items: MenuItemConfig[];
/**
* 分组显示顺序
* 包含组 ID 的字符串数组。
* 例如: ['view', 'edit', 'tools']
* 未在此数组中定义的组将按默认顺序排在最后。
*/
groupOrder?: string[];
}
/**
* 模型加载选项
* 用于配置模型的位置、旋转和缩放
@@ -538,6 +688,51 @@ export declare interface OptButton extends ButtonConfig {
children?: OptButton[];
}
/**
* 右键菜单管理器 (RightKeyManager)
* 负责协调右键交互流程:
* 1. 监听 Canvas/容器的 contextmenu 事件
* 2. 通过注册的处理器 (Handler) 获取需要显示的菜单项
* 3. 实例化 Menu 组件并装载到 RightKey 容器中显示
*/
declare class RightKeyManager extends BimComponent {
private container;
private rightKeyPanel;
private contextHandlers;
constructor(engine: BimEngine, container: HTMLElement);
private initEventListeners;
destroy(): void;
/**
* 注册上下文菜单处理器
* @param handler 处理函数,接收鼠标事件,返回菜单项数组
*/
registerHandler(handler: (e: MouseEvent) => MenuItemConfig[] | null): void;
/**
* 手动显示菜单
* 允许外部直接调用以显示特定的菜单,不一定依赖右键事件
* @param x 屏幕 X 坐标
* @param y 屏幕 Y 坐标
* @param items 菜单项列表
* @param groupOrder 可<><E58FAF>的分组顺序
*/
showMenu(x: number, y: number, items: MenuItemConfig[], groupOrder?: string[]): void;
/**
* 隐藏右键菜单
*/
hide(): void;
/**
* 处理右键点击事件
*/
private handleContextMenu;
}
declare interface RightKeyOptions {
/** 自定义 CSS 类名 */
className?: string;
/** 层级 (z-index) */
zIndex?: number;
}
declare type ThemeChangeListener = (theme: ThemeConfig) => void;
/**