# useTableTreeState

## 使用方法

`useTableTreeData` 的配套状态工具。展开集合由它管（受控或不受控都行），嵌套数据也由它拍平成可见的行。收起的分支是真的不渲染，不是藏起来，所以表体里正好只有看得见的那些行。它会返回 `expandAll` / `collapseAll` 两个方法、给表头全展开开关用的汇总状态 `isAllExpanded`（true/false/indeterminate），以及一个拿来就能用的 `plugin`。注意：收起的行不渲染，所以收起的子树里组件自己的局部状态会丢；需要活下来的状态往上抬。

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

## 示例

### useTableTreeState —— 树形表格

嵌套的行被拍平成可见的行，展开集合由这个 hook 管。表头的开关可以一次展开所有分支，点有子行的行也能展开。

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

interface Node extends Record<string, unknown> {
  id: string
  name: string
  owner: string
  children?: Node[]
}

const nodes: Node[] = [
  {
    id: 'platform',
    name: 'Platform',
    owner: 'Ada',
    children: [
      { id: 'api', name: 'API', owner: 'Grace' },
      {
        id: 'web',
        name: 'Web',
        owner: 'Lin',
        children: [
          { id: 'docs', name: 'Docs', owner: 'Maya' },
        ],
      },
    ],
  },
  { id: 'design', name: 'Design', owner: 'Noah' },
]

const columns: TableColumn<Node>[] = [
  { key: 'name', header: 'Name', width: proportional(2) },
  { key: 'owner', header: 'Owner', width: proportional(1) },
]

const { visibleData, plugin: treePlugin } = useTableTreeState<Node>({
  data: nodes,
  idKey: 'id',
  defaultExpandedIds: ['platform'],
  hasExpandAllControl: true,
  hasRowClickExpansion: true,
})
</script>

<template>
  <Table
    :data="visibleData"
    :columns="columns"
    id-key="id"
    has-hover
    :plugins="{ tree: treePlugin }"
  />
</template>
```

## 属性

`data` 是 `MaybeRefOrGetter`：树会变的时候，传 getter 或 ref。其它字段从你传入的配置对象上读。

## 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `data` | `MaybeRefOrGetter<readonly T[]>` | — | 嵌套数据：行可以在 `childrenKey` 指向的属性下带子行。完全是拍平数据（哪都没有子行）时插件什么都不做，所以可以先用着，等数据变成层级结构再说。 |
| `idKey` | `(keyof T & string) \| ((item: T) => string \| number)` | — | 行 ID 的取法：写属性名，或者给一个返回唯一 id 的函数。 |
| `childrenKey` | `string` | `'children'` | 存放子行数组的属性名。 |
| `defaultExpandedIds` | `Iterable<string>` | — | 不受控模式下初始的展开行 id，只在初始化时读一次。传了 `expandedIds` 就忽略它。 |
| `expandedIds` | `ReadonlySet<string>` | — | 受控的展开行 id 集合，配合 `onExpandedIdsChange` 使用。 |
| `onExpandedIdsChange` | `(ids: ReadonlySet<string>) => void` | — | 展开状态一变化就带着下一个集合调到（两种模式都调）。懒加载场景就在这里去拉子行。 |
| `isItemExpandable` | `(item: T) => boolean` | 有子行才算 | 这一行要不要显示展开箭头。默认只看子行为不为空，这个函数可以盖掉默认判断；懒加载时用得上，子行还没拉回来也能算可展开。 |
| `sortSiblings` | `(siblings: T[]) => T[]` | — | 拍平时给每一组同级行单独排序；子行始终紧跟在父行下面。用来把列的排序和树的顺序合起来。 |
| `indent` | `'sm' \| 'md' \| 'lg'` | `'md'` | 每层的缩进档位（spacing-3 / spacing-4 / spacing-6），会传给 `useTableTreeData`。 |
| `treeColumnKey` | `string` | 插件之外的第一列 | 承载缩进和展开箭头的列，会传给 `useTableTreeData`。 |
| `hasExpandAllControl` | `boolean` | `false` | 在树列表头放全部展开/全部收起的开关。 |
| `hasRowClickExpansion` | `boolean` | `false` | 点可展开行的任意位置就切换展开，会传给 `useTableTreeData`。 |

## 返回值

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `visibleData` | `ComputedRef<T[]>` | 要渲染的行：父行在前，展开的父行后面紧跟子行。作为 `data` 传给表格。 |
| `plugin` | `TablePlugin` | 树插件，已经和可见行、展开集合接好了。塞进 `plugins` 的任意一个键就行。 |
| `expandedIds` | `ComputedRef<ReadonlySet<string>>` | 当前在用的展开集合：受控时是你给的那个，否则是内部维护的。 |
| `isAllExpanded` | `ComputedRef<boolean \| 'indeterminate'>` | 所有可展开行汇总出来的展开状态。 |
| `expandAll` | `() => void` | 展开所有可展开的行，并把新集合通过 `onExpandedIdsChange` 报出去。 |
| `collapseAll` | `() => void` | 收起所有行，并把空集合通过 `onExpandedIdsChange` 报出去。 |
