---
title: "IconPicker"
description: "选取图标并返回标识符字符串的选择器"
category: Form
status: beta
since: 0.6.0
tags: [icon, picker, emoji, brand, file]
syncStatus: reviewed
verified: true
---

## 用法

### 触发器与内联
`inline` 直接渲染面板，`sections` 限定开放的分区。
:::TuffDemoWrapper{demo="IconPickerIconPickerDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import type { IconPickerShape } from '@talex-touch/tuffex/icon-picker'
  import { TxIconPicker } from '@talex-touch/tuffex/icon-picker'
  import { ref } from 'vue'

  const identifier = ref('emoji:🚀')
  const shape = ref<IconPickerShape>('rounded')
  </script>

  <template>
    <TxIconPicker v-model="identifier" v-model:shape="shape" shape-selectable />
    <TxIconPicker v-model="identifier" inline :sections="['icon', 'brand']" />
  </template>
---
:::

### 最佳实践

- 原样存储标识符，渲染时用 `parseIconIdentifier` 解析；不要拆成两列，否则两列可能互相矛盾。
- 只读取存量值的模块从 `@talex-touch/tuffex/icon-picker` 单独引入 `parseIconIdentifier`，不必加载面板。
- 宿主自己画底板时关闭 `shapeSelectable`，否则用户选中的形状看不到。
- 展示小图标底板用 `TxIconChip`；本组件只负责选择。

## API 参考

### 属性

| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `modelValue` | `string` | `''` | 图标标识符，配合 `v-model`。 |
| `shape` | `'circle' \| 'rounded' \| 'square'` | `'rounded'` | 底板形状，配合 `v-model:shape`。 |
| `sections` | `IconPickerSection[]` | 四个分区 | 开放的分区，按标签顺序；`file` 显示为选择文件的按钮。 |
| `catalog` | `Partial<Record<'emoji' \| 'icon' \| 'brand', IconPickerEntry[]>>` | - | 替换分区的内置行；自带图标集的宿主整组替换。 |
| `shapeSelectable` | `boolean` | `true` | 显示形状选择行；宿主自己画底板时关闭。 |
| `fileChooser` | `() => Promise<string \| null>` | - | 宿主的文件对话框，返回绝对路径，取消时为 `null`。 |
| `accept` | `string` | `'image/*'` | 文件对话框与回退 input 的接受列表。 |
| `disabled` | `boolean` | `false` | 禁用触发器与面板。 |
| `size` | `number` | `44` | 触发器底板边长（px）。 |
| `placeholder` | `string` | `''` | 触发器的 `aria-label`；为空时使用搜索文案。 |
| `inline` | `boolean` | `false` | 直接渲染面板，不收在触发器后。 |
| `labels` | `Partial<IconPickerLabels>` | 英文默认值 | 分区标题、搜索占位与清除、选择文件等文案。 |

### 事件

| 事件 | 载荷 | 说明 |
|------|------|------|
| `update:modelValue` | `string` | 选中图标时触发，清除时为 `''`。 |
| `update:shape` | `IconPickerShape` | 形状变化时触发。 |
| `change` | `string` | 与 `update:modelValue` 同时触发。 |
| `file-error` | `unknown` | 文件选择器抛错或回退 input 读取失败时触发。 |

### 暴露方法

| 名称 | 类型 | 说明 |
|------|------|------|
| `toggle(value?)` | `(value?: boolean) => void` | 按 `value` 打开或关闭面板，省略时切换；`inline` 面板始终显示。 |

## 标识符

选中结果是 `<type>:<value>` 字符串。以**第一个**冒号分隔，value 中可再含冒号（`url:`、Windows 的 `file:C:/…`）。

```
emoji:🚀
class:i-ri-rocket-line
file:/Users/me/a.png
url:https://example.com/y.svg
builtin:star
```

`parseIconIdentifier` 与 `formatIconIdentifier` 负责双向转换。不带前缀的字符串不做猜测，返回 `null`；唯一例外是纯表情。

```ts
import { parseIconIdentifier } from '@talex-touch/tuffex/icon-picker'

parseIconIdentifier('class:i-ri-rocket-line') // { type: 'class', value: 'i-ri-rocket-line' }
parseIconIdentifier('rocket.png')             // null
parseIconIdentifier('🚀')                      // { type: 'emoji', value: '🚀' }
```

## 安全名单（Safelist）

使用原子化 CSS 引擎的宿主必须把 `ICON_CATALOG_CLASSES` 加入 safelist，否则网格中的图标都渲染为空白方块。直接展开模块导出，不要复制字符串。

```ts
import { ICON_CATALOG_CLASSES } from '@talex-touch/tuffex/icon-picker'

export default defineConfig({
  safelist: [...ICON_CATALOG_CLASSES],
})
```

## 概述

- 文件分区由宿主提供能力：传入 `fileChooser`（如 Electron 的 `dialog.showOpenDialog` 桥接）；未传时回退到隐藏的 `<input type="file">`，结果为 data URL。
- 搜索匹配 `keywords` 而不是 id；内置目录的关键词为中英双语。
- `shape` 只是表现，单独存储，不属于标识符。

## 技术实现

- 标识符工具：`src/identifier.ts`。
- 源码：`packages/tuffex/packages/components/src/icon-picker/`。
