# useTableTreeData

## Usage

Headless tree plugin for Table: renders nested rows with per-level indentation and expand/collapse chevrons in the tree column (the first column by default), and reflects hierarchy on body rows via `aria-level` and `aria-expanded`. Composable with the other Table plugins: the canonical plugin order places tree before selection, so the checkbox column lands left of the indented tree column. Feed it the config that `useTableTreeState` builds for you, or construct the config directly for server-driven or pre-flattened trees. When no row is expandable (flat data), every transform is a pass-through and the table renders identically to one without the plugin. Known limitation: the tree column wraps its cell content, so `textOverflow="truncate"` tooltips do not apply within the tree column.

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

## Examples

### useTableTreeData — Tree Table

Child rows reuse the same columns, indented per level, with an expand/collapse chevron in the tree column. The header control expands every branch.

```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>
```

## Properties

The config is a `MaybeRefOrGetter`, so pass a getter to keep the row meta, the expand-all state, and the toggles live.

## Parameters

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `getRowMeta` | `(item: T) => TableTreeRowMeta \| undefined` | — | Structural meta for a visible row: `{ id, level (0-based), hasChildren, isExpanded }`. Return `undefined` for a row that is not part of the tree. |
| `onToggleItem` | `(item: T) => void` | — | Toggle a row's expansion. |
| `hasExpandableRows` | `boolean` | — | Whether any row in the dataset is expandable. When false the plugin is a no-op: no expanders, no indent, no tree ARIA. |
| `hasExpandAllControl` | `boolean` | `false` | Show an expand-all/collapse-all toggle in the tree column header. Requires `isAllExpanded` plus `onExpandAll` / `onCollapseAll`. |
| `isAllExpanded` | `boolean \| 'indeterminate'` | — | Aggregate expansion state across every expandable row, driving the header expand-all toggle. `true` when all are expanded, `false` when none are, `'indeterminate'` when some are. |
| `onExpandAll` | `() => void` | — | Expand every expandable row. Wired to the header control. |
| `onCollapseAll` | `() => void` | — | Collapse every row. Wired to the header control. |
| `indent` | `'sm' \| 'md' \| 'lg'` | `'md'` | Indent step per level, mapped to the spacing-3 / spacing-4 / spacing-6 tokens. |
| `treeColumnKey` | `string` | the first column no plugin added | Column that carries the indent + expander. When the key is not found, the first column that did not come from a plugin is used. |
| `hasRowClickExpansion` | `boolean` | `false` | When true, clicking anywhere on an expandable row toggles its expansion, in addition to the chevron. A pointer-only convenience: keyboard and assistive-tech users toggle via the chevron button. Clicks on interactive cell content (buttons, links, form controls) or a text selection do not toggle. Leaf rows stay inert, and it is a no-op on flat data. |

## Returns

| Field | Type | Description |
| --- | --- | --- |
| `transformColumns` | `(columns: TableColumn[]) => TableColumn[]` | Wraps the cell renderer of the tree column so it draws the level indent, the chevron, and the cell content. Columns come back untouched while `hasExpandableRows` is false or no tree column is found. |
| `headerPatch` | `(column: TableColumn) => TableHeaderPatch \| null` | Puts the expand-all / collapse-all button in front of the tree column header text. Returns `null` for other columns, when `hasExpandAllControl` is off, or when the three expand-all fields are missing. |
| `rowPatch` | `(row: T, index: number, columnCount: number) => TableRowPatch \| null` | Sets `aria-level` (level + 1) and, for rows with children, `aria-expanded`. With `hasRowClickExpansion` it also adds the click-to-toggle handler and the `astryx-table__clickable` class on expandable rows. |
