# Input

单行文本输入框，支持受控/非受控值、多种尺寸、前后缀及清除按钮。

## 适用场景

- 表单中的文本、数字、邮箱、密码等单行内容输入
- 搜索框，需要前后缀图标
- 需要一键清除内容的输入场景
- 需要在输入框失焦后自动去除首尾空格

## Props

### Input Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `""` | 否 | 自定义 class |
| value | `string \| number` | `-` | 否 | 输入值（受控） |
| defaultValue | `string \| number` | `""` | 否 | 默认值（非受控） |
| type | `"number" \| "text" \| "tel" \| "email" \| "password"` | `-` | 否 | 输入类型 |
| size | `"md" \| "sm" \| "xs" \| "lg" \| "xl"` | `-` | 否 | 尺寸，默认跟随 ConfigContext `baseSize` |
| disabled | `boolean` | `-` | 否 | 是否禁用 |
| status | `"normal" \| "error"` | `"normal"` | 否 | 文本框状态 |
| withClear | `boolean` | `false` | 否 | 是否提供清除按钮 |
| trimOnBlur | `boolean` | `true` | 否 | 是否在 blur 时对 value 进行 trim |
| prefix | `ReactNode` | `-` | 否 | 输入框内前缀 |
| suffix | `ReactNode` | `-` | 否 | 输入框内后缀 |
| onChange | `(e: ChangeEvent<HTMLInputElement> \| FocusEvent<HTMLInputElement, Element>) => void` | `-` | 否 | 值变化时的回调 |
| onPressEnter | `(e: KeyboardEvent<HTMLInputElement>) => void` | `-` | 否 | 按下回车的回调 |
| onKeyDown | `(e: KeyboardEvent<HTMLInputElement>) => void` | `-` | 否 | 按下按键的回调 |
| onClickClear | `(e: MouseEvent<Element, MouseEvent>) => void` | `-` | 否 | 点击清除按钮的回调 |

### InputWrapper Props

用于实现类 Input 组件的包裹容器（如 RangePicker），为纯 UI 型组件。

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `""` | 否 | 自定义 class |
| focus | `boolean` | `false` | 否 | 是否呈现聚焦样式（不在内部维护，需外部传入） |
| prefixInnerPadding | `number` | `0` | 否 | 前缀内边距 |
| suffixInnerPadding | `number` | `0` | 否 | 后缀内边距 |
| size | `"md" \| "sm" \| "xs" \| "lg" \| "xl"` | `-` | 否 | 尺寸，默认跟随 ConfigContext `baseSize` |
| prefix | `ReactNode` | `-` | 否 | 输入框内前缀 |
| suffix | `ReactNode` | `-` | 否 | 输入框内后缀 |
| disabled | `boolean` | `false` | 否 | 是否禁用 |
| status | `"normal" \| "error"` | `"normal"` | 否 | 文本框状态 |
| onClick | `(e: MouseEvent<HTMLDivElement, MouseEvent>) => void` | `-` | 否 | 点击回调 |
| onMouseEnter | `(e: MouseEvent<HTMLDivElement, MouseEvent>) => void` | `-` | 否 | 鼠标移入回调 |
| onMouseLeave | `(e: MouseEvent<HTMLDivElement, MouseEvent>) => void` | `-` | 否 | 鼠标移出回调 |
| refWrapper | `(node: HTMLDivElement) => void` | `-` | 否 | 外层容器的 ref 回调 |

## 典型用法

### 基础用法

```tsx
const [value, setValue] = useState('')

<Input value={value} onChange={e => setValue(e.target.value)} placeholder={'name'} />
<Input defaultValue={'invalid'} status={'error'} />
<Input defaultValue={'小明'} disabled />
```

### 尺寸

```tsx
const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const

{sizes.map(size => (
    <Input key={size} size={size} placeholder={size} />
))}
```

### 前缀与后缀

```tsx
<Input prefix={'这是前缀'} />
<Input suffix={'这是后缀'} />
<Input prefix={<Icon svg={SvgBell} />} suffix={<Icon svg={SvgSearch} />} />
```

### 清除按钮

```tsx
const [value, setValue] = useState('')

<Input withClear value={value} onChange={e => setValue(e.target.value)} />
<Input withClear suffix={<Icon svg={SvgBell} />} />
```

### InputWrapper 用法

> `InputWrapper` 的 focus 状态不在内部维护，需要外部传入 `props.focus: true` 以体现聚焦样式，常用于 RangePicker 等组合输入场景

```tsx
<InputWrapper
    focus={isFocused}
    status={hasError ? 'error' : undefined}
    disabled={disabled}
    suffix={<Icon svg={SvgSearch} />}
    suffixInnerPadding={12}
>
    <input disabled={disabled} />
    <span>~</span>
    <input disabled={disabled} />
</InputWrapper>
```

## 注意事项

- 组件不支持 `props.style`，样式定制请使用 `className`
- `readonly` 与 `disabled` 样式一致，推荐始终使用 `disabled` 替代 `readonly`
- `trimOnBlur` 默认为 `true`，输入框失焦时会自动去除首尾空格
- 字数长度限制相关处理请参见 Textarea 组件 FAQ
