# useTableColumnSettings

## Usage

Headless column visibility and ordering management for Table. The plugin keeps only the columns whose key is in `activeColumnKeys`, in that array's order, so one list drives both your column picker and the table. `useTableColumnSettingsState` is the toggle helper: it holds the keys, puts `isAlwaysVisible` columns back when they are removed, and knows which set to restore for "Reset to default".

```ts
import { useTableColumnSettings, useTableColumnSettingsState } from '@astryx-vue/core/Table'
```

The config is read again on every access, so pass a getter when the keys live in a `ref`. A plain object works too, but the table keeps the keys it saw first.

The picker itself is yours to build. `MultiSelector` takes `{ value, label, disabled }` options, so map each column to that shape and mark `isAlwaysVisible` ones as disabled. Give an option a `group` and you can render the columns under headings.

`defaultColumnKeys` is the column set behind "Reset to default". Without it, resetting shows every column.

```ts
const state = useTableColumnSettingsState({
  columns: columnOptions,
  activeColumnKeys: activeKeys,
  onChangeActiveColumnKeys(keys) {
    activeKeys.value = [...keys]
  },
  defaultColumnKeys: ['name', 'email'],
})
```

`resetToDefault()` hands `defaultColumnKeys` to `onChangeActiveColumnKeys`; `showAllColumns()` hands every column instead. The two are what the reset button and the "select all" row in a picker call.

`useTableColumnSettings()` hides and reorders columns. It does not decide which columns exist; the table still receives every column, and the plugin drops the ones that are turned off.

## Examples

### Table — Column Settings

Table with a column visibility picker in the toolbar. Toggle columns on and off; the Name column always stays.

```vue
<script setup lang="ts">
import type { ColumnSettingsOption, TableColumn } from '@astryx-vue/core/Table'
import { MultiSelector } from '@astryx-vue/core/MultiSelector'
import { Stack } from '@astryx-vue/core/Stack'
import { proportional, Table, useTableColumnSettings, useTableColumnSettingsState } from '@astryx-vue/core/Table'
import { Text } from '@astryx-vue/core/Text'
import { Toolbar } from '@astryx-vue/core/Toolbar'
import { ref } from 'vue'

interface User extends Record<string, unknown> {
  id: string
  name: string
  email: string
  role: string
  department: string
  status: string
}

const users: User[] = [
  { id: '1', name: 'Alice Johnson', email: 'alice@example.com', role: 'Engineer', department: 'Platform', status: 'Active' },
  { id: '2', name: 'Bob Smith', email: 'bob@example.com', role: 'Designer', department: 'Product', status: 'Active' },
  { id: '3', name: 'Charlie Brown', email: 'charlie@example.com', role: 'Manager', department: 'Platform', status: 'Away' },
  { id: '4', name: 'Diana Prince', email: 'diana@example.com', role: 'Engineer', department: 'Infra', status: 'Active' },
  { id: '5', name: 'Eve Davis', email: 'eve@example.com', role: 'Admin', department: 'Operations', status: 'Inactive' },
]

const allColumns: TableColumn<User>[] = [
  { key: 'name', header: 'Name', width: proportional(1) },
  { key: 'email', header: 'Email', width: proportional(2) },
  { key: 'role', header: 'Role', width: proportional(1) },
  { key: 'department', header: 'Department', width: proportional(1) },
  { key: 'status', header: 'Status', width: proportional(1) },
]

const columnOptions: ColumnSettingsOption<string>[] = [
  { key: 'name', label: 'Name', isAlwaysVisible: true },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'department', label: 'Department' },
  { key: 'status', label: 'Status' },
]

const activeKeys = ref(columnOptions.map(column => column.key))
const state = useTableColumnSettingsState<string>({
  columns: columnOptions,
  activeColumnKeys: activeKeys,
  onChangeActiveColumnKeys(keys) {
    activeKeys.value = [...keys]
  },
})
const plugin = useTableColumnSettings<User>(state.columnSettingsConfig)
const selectorOptions = columnOptions.map(column => ({
  value: column.key,
  label: column.label,
  disabled: column.isAlwaysVisible === true,
}))

function onColumnsChange(keys: (string | number)[]) {
  state.setActiveColumnKeys(keys.map(String))
}
</script>

<template>
  <Stack direction="vertical" :gap="3" width="100%">
    <Toolbar label="Table actions">
      <template #start>
        <Text type="label">
          Team
        </Text>
      </template>
      <template #end>
        <MultiSelector
          label="Columns"
          label-hidden
          :options="selectorOptions"
          :model-value="[...state.activeColumnKeys]"
          @update:model-value="onColumnsChange"
        />
      </template>
    </Toolbar>
    <Table
      :data="users"
      :columns="allColumns"
      id-key="id"
      has-hover
      :plugins="{ columnSettings: plugin }"
    />
  </Stack>
</template>
```

## Parameters

`useTableColumnSettings()` takes one config object. Wrap it in a getter or a `ref` so the table reads the current keys: `useTableColumnSettings(() => state.columnSettingsConfig)`.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `columns` | `readonly ColumnSettingsOption[]` | — | Required. All available columns with metadata for the settings UI. Each entry has `key`, `label`, and optional `isAlwaysVisible` and `group`. |
| `activeColumnKeys` | `readonly TColumnKey[]` | — | Required. Currently active column keys, in display order. Only columns with keys in this array are shown. |
| `onChangeActiveColumnKeys` | `(keys: TColumnKey[]) => void` | — | Called when active columns change. `useTableColumnSettings()` never calls it; it belongs to the config that `useTableColumnSettingsState()` hands back. |
| `defaultColumnKeys` | `readonly TColumnKey[]` | — | Default column set for "Reset to default". When omitted, reset shows all columns. |

## Returns

`useTableColumnSettings()` returns one `TablePlugin&lt;T&gt;`. Pass it to `Table` in `plugins`. The plugin fills one field of the plugin contract:

| Name | Type | Description |
| --- | --- | --- |
| `transformColumns` | `(columns: TableColumn[]) => TableColumn[]` | Drops the columns that are not in `activeColumnKeys`, then sorts the rest into that array's order. |

## useTableColumnSettingsState

The companion hook. It holds the keys, and every write goes through it so `isAlwaysVisible` columns cannot be removed.

```ts
const state = useTableColumnSettingsState({
  columns: columnOptions,
  activeColumnKeys: activeKeys,
  onChangeActiveColumnKeys(keys) {
    activeKeys.value = [...keys]
  },
})
const plugin = useTableColumnSettings(state.columnSettingsConfig)
```

It takes the same fields as the config plus `defaultColumnKeys`.

| Name | Type | Description |
| --- | --- | --- |
| `activeColumnKeys` | `readonly TColumnKey[]` | The keys you passed in, read through on every access. |
| `toggleColumn` | `(key: TColumnKey) => void` | Turns one column on or off. An `isAlwaysVisible` key is ignored. |
| `isColumnActive` | `(key: TColumnKey) => boolean` | Whether the column is currently shown. Use it to check a picker option. |
| `isColumnToggleable` | `(key: TColumnKey) => boolean` | Whether the column may be turned off. `false` for `isAlwaysVisible` columns, which is what disables their picker option. |
| `showAllColumns` | `() => void` | Reports every column in `columns` as active. |
| `resetToDefault` | `() => void` | Reports `defaultColumnKeys`, or every column when it is not set. This is what a "Reset to default" button calls. |
| `setActiveColumnKeys` | `(keys: readonly TColumnKey[]) => void` | Reports the given keys with every `isAlwaysVisible` key added back, then calls `onChangeActiveColumnKeys`. |
| `columnSettingsConfig` | `UseTableColumnSettingsConfig` | Config for `useTableColumnSettings()`, wired to `setActiveColumnKeys` and carrying `defaultColumnKeys`. |

### ColumnSettingsOption

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `key` | `TColumnKey` | — | Column key. It must match a `TableColumn.key`. |
| `label` | `string` | — | Human-readable label for the settings UI. |
| `isAlwaysVisible` | `boolean` | `false` | The column cannot be hidden. Use it for essential columns such as Name or ID. |
| `group` | `string` | — | Optional group name for organized column lists. Columns with the same group are rendered together under a heading. |
