# RightKey 组件详细文档

> 本文档详细描述 RightKey 组件的实现细节，包括 API、UI 结构、逻辑流程等，供 AI 根据文档重现组件。

---

## 1. 组件概述

### 1.1 基本信息
- **组件名称**: `BimRightKey`
- **文件路径**: `src/components/right-key/index.ts`
- **类型定义**: `src/components/right-key/types.ts`
- **样式文件**: `src/components/right-key/index.css`
- **实现接口**: `IBimComponent`
- **用途**: 提供一个全屏感知的定位容器，用于显示右键菜单等浮层内容。
- **特点**: 自动边界检测（防止溢出屏幕）、点击外部自动关闭、内容无关性（支持挂载任意内容）。

### 1.2 在 SDK 中的位置
- RightKey 是右键菜单系统的容器部分。
- 必须通过 `RightKeyManager` 使用，不允许直接使用。
- `RightKeyManager` 位于 `src/managers/right-key-manager.ts`。

---

## 2. 组件类 API 文档

### 2.1 构造函数

```typescript
constructor(options?: RightKeyOptions)
```

**��数**:
- `options`:
  - `zIndex`: number (默认 10000)
  - `className`: string

### 2.2 公共方法

#### `init(): void`
初始化组件（实现 `IBimComponent` 接口）

**功能**:
- 创建 DOM 结构
- 将容器挂载到 `document.body`（或其他指定容器，当前实现是 body）
- 绑定全局 `mousedown` 事件用于检测“点击外部”

#### `mount(content: IRightKeyContent): void`
挂载内容组件

**参数**:
- `content`: 实现了 `IRightKeyContent` 接口的对象（如 `BimMenu`）

**功能**:
- 清空当前容器内容
- 调用 `content.getElement()` 并将结果 append 到容器中
- 保存 content 引用

#### `unmountContent(): void`
卸载内容

**功能**:
- 调用 `content.destroy()`
- 清空容器 DOM

#### `show(x: number, y: number): void`
显示容器

**参数**:
- `x`, `y`: 屏幕坐标（通常是鼠标事件的 `clientX/Y`）

**功能**:
- 计算容器尺寸
- 执行边界检测算法，调整坐标防止溢出
- 设置 `top/left` 样式
- 设置 `display: block`

#### `hide(): void`
隐藏容器

**功能**:
- 设置 `display: none`
- 触发 `onClose` 回调（如果设置了）

#### `setOnClose(callback: () => void): void`
设置关闭回调

**功能**:
- 注册一个回调函数，在容器被隐藏（如点击外部）时触发。通常用于通知 Manager 清理状态。

#### `destroy(): void`
销毁组件

**功能**:
- 解绑全局事件
- 卸载内容
- 移除自身 DOM

---

## 3. Manager API 文档

### 3.1 RightKeyManager 类

**文件路径**: `src/managers/right-key-manager.ts`

#### `registerHandler(handler: (e) => MenuItemConfig[] | null): void`
注册上下文菜单处理器

**参数**:
- `handler`: 函数，接收 MouseEvent，返回菜单配置数组或 null。

**功能**:
- 将 handler 加入内部列表。
- 右键点击时，遍历列表。只要有一个 handler 返回了非空数组，就显示这些菜单项。

#### `showMenu(x, y, items, groupOrder?): void`
手动显示菜单

**功能**:
- 创建 `BimMenu` 实例
- 调用 `rightKeyPanel.mount(menu)`
- 调用 `rightKeyPanel.show(x, y)`

---

## 4. UI 详细描述

### 4.1 DOM 结构

```html
<!-- 容器 -->
<div class="bim-right-key" style="z-index: 9000; display: none; left: ...; top: ...">
    <!-- 挂载的内容 (例如 BimMenu 的 ul) -->
    <ul class="bim-menu">...</ul>
</div>
```

### 4.2 CSS 类名

#### `.bim-right-key`
- `position: fixed`: 固定定位，相对于视口。
- `display: none`: 默认隐藏。
- `box-shadow`: 即使内容组件没有阴影，容器也可以提供（当前��要由内容组件自己提供）。

---

## 5. 逻辑流程详细描述

### 5.1 全局点击检测 (`handleGlobalClick`)

组件初始化时，会在 `document` 上绑定 `mousedown` (捕获阶段或冒泡阶段，通常冒泡即可)。

1.  当 `mousedown` 发生时，检查 `event.target`。
2.  如果 `target` 位于 `.bim-right-key` 容器内部，**不做处理**（认为是有效的内部交互）。
3.  如果 `target` 在容器外部，调用 `hide()` 关闭菜单。

**注意**: 子菜单（SubMenu）通常挂载在 `body` 上，物理上位于 `.bim-right-key` 外部。为了防止点击子菜单时误关主菜单，子菜单容器必须阻止 `mousedown` 冒泡（见 Menu 组件文档）。

### 5.2 边界检测算法

在 `show(x, y)` 时执行：

1.  获取容器尺寸: `rect = element.getBoundingClientRect()`
2.  获取视口尺寸: `winW = window.innerWidth`, `winH = window.innerHeight`
3.  **水平调整**:
    - 如果 `x + rect.width > winW`: `x = x - rect.width`（向左展开）
    - 否则: `x` 保持不变（向右展开）
4.  **垂直调整**:
    - 如果 `y + rect.height > winH`: `y = y - rect.height`（向上展开）
    - 否则: `y` 保持不变（向下展开）
5.  应用调整后的 `x, y` 到 `style.left` 和 `style.top`。

---

## 6. 类型定义

### 6.1 IRightKeyContent

```typescript
interface IRightKeyContent {
    getElement(): HTMLElement;
    destroy(): void;
}
```

### 6.2 RightKeyOptions

```typescript
interface RightKeyOptions {
    className?: string;
    zIndex?: number;
}
```

---

## 7. 文件清单

- `src/components/right-key/index.ts`: 组件核心逻辑
- `src/components/right-key/index.css`: 样式
- `src/components/right-key/types.ts`: 类型定义
- `src/managers/right-key-manager.ts`: 管理器

---

## 8. 更新记录

| 日期 | 修改内容 | 修改人 |
|------|---------|--------|
| 2024-XX-XX | 更新 Manager API 以支持 MenuItemConfig | AI Assistant |