# useTableFilterState

## 使用方法

管表格过滤状态。它交出当前的过滤映射、一个改值的处理函数，还有一个清空的办法。把映射和处理函数交给 `useTableFiltering`，把映射交给 `applyTableFilters()` 就能拿到匹配的行。

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

一条过滤「关掉」的意思是它的 key 不在映射里。写 `null`、空字符串或空数组时，key 会被删掉，而不是存一个空值，所以映射里还留着的 key 一定是生效的过滤。

需要打开页面就带着过滤时，给一个初始映射。可以直接把映射传进去，也可以写成 `initialState`。初始对象是浅拷贝的，后面怎么写都不会改到你传进去的那份。

```ts
const direct = useTableFilterState({ role: 'Engineer' })
const wrapped = useTableFilterState({ initialState: { role: 'Engineer' } })
```

## 示例

### Table — 行内过滤

行内过滤控件，过滤映射由 useTableFilterState 保存。

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

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

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

const fields: TableFilterField[] = [
  { key: 'name', type: 'string', label: 'Name' },
  { key: 'email', type: 'string', label: 'Email' },
  {
    key: 'role',
    type: 'enum',
    label: 'Role',
    options: [
      { value: 'Engineer', label: 'Engineer' },
      { value: 'Designer', label: 'Designer' },
      { value: 'Manager', label: 'Manager' },
      { value: 'Admin', label: 'Admin' },
    ],
  },
]

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

const { filters, onFilterChange } = useTableFilterState()
const filterPlugin = useTableFiltering<Employee>(() => ({
  filters: filters.value,
  onFilterChange,
  fields,
  variant: 'inline',
}))
const rows = computed(() => applyTableFilters(employees, filters.value, fields))
</script>

<template>
  <Table
    :data="rows"
    :columns="columns"
    id-key="id"
    :plugins="{ filter: filterPlugin }"
  />
</template>
```

### Table — 弹出过滤

弹出层里的过滤控件，用的是同一份受管状态。

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

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

const employees: Employee[] = [
  { id: '1', name: 'Alice', email: 'alice@example.com', role: 'Engineer', department: 'Platform' },
  { id: '2', name: 'Bob', email: 'bob@example.com', role: 'Designer', department: 'Product' },
  { id: '3', name: 'Charlie', email: 'charlie@example.com', role: 'Manager', department: 'Platform' },
  { id: '4', name: 'Diana', email: 'diana@example.com', role: 'Engineer', department: 'Infrastructure' },
  { id: '5', name: 'Eve', email: 'eve@example.com', role: 'Admin', department: 'Operations' },
]

const fields: TableFilterField[] = [
  { key: 'name', type: 'string', label: 'Name' },
  { key: 'email', type: 'string', label: 'Email' },
  {
    key: 'role',
    type: 'enum',
    label: 'Role',
    options: [
      { value: 'Engineer', label: 'Engineer' },
      { value: 'Designer', label: 'Designer' },
      { value: 'Manager', label: 'Manager' },
      { value: 'Admin', label: 'Admin' },
    ],
  },
]

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

const { filters, onFilterChange } = useTableFilterState()
const filterPlugin = useTableFiltering<Employee>(() => ({
  filters: filters.value,
  onFilterChange,
  fields,
}))
const rows = computed(() => applyTableFilters(employees, filters.value, fields))
</script>

<template>
  <Table
    :data="rows"
    :columns="columns"
    id-key="id"
    :plugins="{ filter: filterPlugin }"
  />
</template>
```

## 参数

`useTableFilterState()` 只有一个可选参数，两种写法都行。

| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `initial` | `TableFilterState` | `{}` | 直接给初始过滤映射。它是浅拷贝的，你传进去的对象不会被写。 |
| `initial.initialState` | `TableFilterState` | `{}` | 把同一份映射放在 `initialState` 键里：`useTableFilterState({ initialState })`。过滤值不可能是对象，所以键名叫 `initialState` 且值是对象时，只可能是这种写法。 |

## 返回值

| 名称 | 类型 | 说明 |
| --- | --- | --- |
| `filters` | `Ref` | 活的过滤映射。读 `filters.value` 拿到当前状态。 |
| `onFilterChange` | `(key: string, value: TableFilterValue \| null) => void` | 设置或清掉一个字段。映射会换成新对象，所以用 getter 读它的地方会跟着更新。 |
| `clearAll` | `() => void` | 清空整张映射。所有过滤一起关掉。 |

### TableFilterState

| 名称 | 类型 | 说明 |
| --- | --- | --- |
| `[fieldKey]` | `TableFilterValue` | 字段 key 到过滤值的映射。`TableFilterValue` 是 `string \| number \| string[]`。 |
