# useTableRowExpansion

## 使用方法

这个组合式函数返回一个 TablePlugin，能在某一行下面展开一整块详情面板，内容由使用方通过 renderExpanded(item) 画出。它会加上一列前置的折叠按钮，并在右键菜单里加一项「展开/折叠行」；被展开的 expandedKeys 集合由你保存。面板横跨整行，但内容从第一列开始、跳过折叠按钮，所以详情和上面的列名对得齐；左侧留白跟着表格密度走。适合主从结构的行（订单详情、表单、图表、嵌套表格）。子行复用父行那些列的层级数据，用 useTableTreeData + useTableTreeState。

```ts
import { useTableRowExpansion } from '@astryx-vue/core/Table'
```

`renderExpanded` 返回 `VNodeChild`，所以用 `h()` 搭面板，或者渲染一个你已经引入的组件。每次读配置都会重新取值：用 getter 传配置，展开集合要换成新对象，不要原地改。

```ts
const expansion = useTableRowExpansion(() => ({
  expandedKeys: expanded.value,
  onToggle: toggle,
  getRowKey: order => order.id,
  renderExpanded: order => h('p', order.note),
}))
```

折叠按钮那一列的 key 是 `__expansion`，插在你的列前面。宽 40px，表头视觉上留空但保留给读屏，不能拖动改宽。

## 示例

### useTableRowExpansion — 行详情

每行都能展开一整块详情面板的表格。点折叠按钮，或者右键一行选展开。

```vue
<script setup lang="ts">
import type { TableColumn } from '@astryx-vue/core/Table'
import { pixel, proportional, Table, useTableRowExpansion } from '@astryx-vue/core/Table'
import { h, ref } from 'vue'

interface Order extends Record<string, unknown> {
  id: string
  customer: string
  total: string
  note: string
}

const orders: Order[] = [
  { id: '1042', customer: 'Northwind', total: '$240', note: 'Two seats, ships Friday.' },
  { id: '1043', customer: 'Contoso', total: '$80', note: 'Gift wrap requested.' },
  { id: '1044', customer: 'Fabrikam', total: '$560', note: 'Hold for pickup.' },
]

const columns: TableColumn<Order>[] = [
  { key: 'id', header: 'Order', width: pixel(100) },
  { key: 'customer', header: 'Customer', width: proportional(1) },
  { key: 'total', header: 'Total', width: pixel(100) },
]

const expanded = ref(new Set<string>(['1042']))

function toggle(key: string) {
  const next = new Set(expanded.value)
  if (next.has(key))
    next.delete(key)
  else
    next.add(key)
  expanded.value = next
}

const expansion = useTableRowExpansion<Order>(() => ({
  expandedKeys: expanded.value,
  onToggle: toggle,
  getRowKey: order => order.id,
  panelVariant: 'muted',
  hasRowClickExpansion: true,
  renderExpanded: order => h('p', order.note),
}))
</script>

<template>
  <Table
    :data="orders"
    :columns="columns"
    id-key="id"
    :plugins="{ expansion }"
  />
</template>
```

## 参数

`useTableRowExpansion()` 只有一个配置对象。用 getter 或 `ref` 包一层，面板才能跟着当前的展开集合走：`useTableRowExpansion(() => ({ ... }))`。

| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `expandedKeys` | `ReadonlySet<string>` | — | 必填。当前展开了的行 key 集合，由你保存。 |
| `onToggle` | `(key: string) => void` | — | 必填。一行的展开状态切换时调用，传入行 key。折叠按钮和右键菜单都会触发。 |
| `getRowKey` | `(item: T) => string` | — | 必填。从一行的数据算出稳定、唯一的 key。 |
| `renderExpanded` | `(item: T) => VNodeChild` | — | 必填。画出展开后那一整行详情面板里的内容，参数是这一行的数据。 |
| `getIsItemExpandable` | `(item: T) => boolean` | — | 决定哪些行能展开。不能展开的行不显示折叠按钮、右键菜单里没有这一项，也永远不会画面板。默认所有行都能展开。 |
| `panelVariant` | `'muted' \| 'transparent'` | `'transparent'` | 详情面板的底色。`'transparent'` 什么都不画：面板是这一行的延续，用表格所在的表面，所以 Card 能透出来，斑马纹也照旧。`'muted'` 会铺一层，表示它是注解而不是又一行数据——只有裸表格、没有卡片、分隔线和斑马纹时才需要它。这层是很低透明度的近黑色，在深色卡片上几乎看不见，所以 `'muted'` 基本只在浅色主题里有明显效果。 |
| `hasRowClickExpansion` | `boolean` | `false` | 点整行就能切换，不只点折叠按钮。这是给指针设备加的方便，按钮仍然是键盘和辅助技术用的那个控件。点在可交互的单元格内容（按钮、链接、表单控件）上，或者正在选中文字时，不会切换；不能展开的行没有反应。 |

## 返回值

`useTableRowExpansion()` 返回一个 `TablePlugin&lt;T&gt;`，放进 `Table` 的 `plugins` 里。它填的是插件协议上的三个字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `transformColumns` | `(columns: TableColumn[]) => TableColumn[]` | 在最前面插入带折叠按钮的 `__expansion` 列。 |
| `rowPatch` | `(row: T, index: number, columnCount: number) => TableRowPatch \| null` | 给这一行的右键菜单加上展开项、接上可选的整行点击，并在展开时挂上面板。不能展开的行返回 `null`。 |
| `cellPatch` | `(input: TableCellPatchInput) => TableCellPatch \| null` | 给折叠按钮那两个单元格加上 `astryx-table__expansion` 类名，保住 40px 的宽度。 |

### TableRowPatch

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `attrs` | `Record<string, string \| undefined>` | 展开的行带上 `data-expanded`。 |
| `class` | `string` | 开了 `hasRowClickExpansion` 时是 `astryx-table__clickable`。 |
| `onClick` | `(event: MouseEvent) => void` | 切换这一行，除非点击落在可交互元素上，或者正在选中文字。 |
| `menu` | `TableRowMenuItem[]` | 只有一项，用来展开或折叠这一行，文案跟着语言走。 |
| `panel` | `TablePanelPatch` | 行下面的详情面板，带 `variant` 和 `render`。只有行展开时才存在。 |
