# Uploader

Uploader 컴포넌트는 파일 업로드를 위한 컴포넌트입니다. [관련 가이드](https://www.figma.com/design/NoAOnaPiP2H2lzvRhkBnGZ/CDS-v1.1?node-id=2600-3701\&t=WLh4JrGHlzDGMeV4-0)는 figma에서도 확인할 수 있습니다.

```tsx
<Uploader
  accept=".png"
  maxFileTotalSize={31457280}
/>
```

| Field            | Description                                                                                                                                                                                                                                                            | Default  |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| accept           | \['허용되는 파일의 확장자.', '\`image/\*\` = \`.jpeg,.jpg,.png,.gif,.bmp,.tiff,.svg,.webp,.heic,.ico\`', '\`video/\*\` = \`.mp4,.avi,.mkv,.mov,.wmv,.flv,.webm,.mpeg,.3gp,.m4v\`', '\`audio/\*\` = \`.mp3,.wav,.flac,.aac,.ogg,.m4a,.wma,.aiff,.alac,.midi,.mp4\`'].join('\n\n') | ".png"   |
| label            | Uploader에 대한 label                                                                                                                                                                                                                                                     | —        |
| error            | —                                                                                                                                                                                                                                                                      | —        |
| disabled         | —                                                                                                                                                                                                                                                                      | —        |
| minCount         | upload 해야하는 최소 파일 개수                                                                                                                                                                                                                                                   | —        |
| maxCount         | upload 가능한 최대 파일 개수                                                                                                                                                                                                                                                    | —        |
| maxFileSize      | upload 가능한 단일 파일 최대 사이즈(MiB)                                                                                                                                                                                                                                           | —        |
| maxFileTotalSize | upload 가능한 최대 사이즈(MiB)                                                                                                                                                                                                                                                 | 31457280 |
| helperText       | 모든 안내 메세지/에러 메세지보다 해당 메세지가 우선적으로 보여진다.                                                                                                                                                                                                                                 | —        |
| onChange         | —                                                                                                                                                                                                                                                                      | —        |
| onDelete         | —                                                                                                                                                                                                                                                                      | —        |

## 기본형

필수 속성 값으로 `accept`, `maxFileTotalSize`를 받고, 해당 속성 값들을 바탕으로 기본 `helperText`가 설정됩니다.\
생성된 `helperText`는 File dropzone 하단에 노출됩니다.

```tsx
<Uploader
  accept=".png"
  maxFileTotalSize={31457280}
/>
```

`label`과 함께 쓰이면 아래와 같은 모습입니다.

```tsx
<Uploader
  accept=".png"
  maxFileTotalSize={31457280}
  label="Click to Upload or drag file"
/>
```

## Size

Size는 `sm`, `md` 두 사이즈를 지원합니다.

```tsx
<Stack gap={4}>
  <Stack gap={2}>
    <Typography level="title-sm">SM</Typography>
    <Uploader {...args} size="sm" />
  </Stack>
  <Stack gap={2}>
    <Typography level="title-sm">MD</Typography>
    <Uploader {...args} size="md" />
  </Stack>
</Stack>
```

## Internal validation

### Min Count

`minCount` 값과 현재 업로드된 상태에 따라서 내부적으로 에러를 발생시킵니다.

```tsx
<>
  <form onSubmit={e => {
    e.preventDefault();
    console.log('Submitted');
  }}>
  <Stack gap={2}>
    <Uploader {...args} />
    <Button type="submit">Submit</Button>
  </Stack>
</form>
</>
```

### Max Count

`maxCount` 값과 현재 업로드된 상태에 따라서 내부적으로 에러를 발생시킵니다.\
아래의 상황에서 두 개 이상의 파일을 업로드 해보세요.

```tsx
<Uploader
  accept=".png"
  maxFileTotalSize={31457280}
  label="Click to Upload or drag file"
  maxCount={3}
  uploaded={[{
  id: '1',
  name: 'file1.jpg',
  size: 1024
}, {
  id: '2',
  name: 'file2.jpg',
  size: 0
}]}
/>
```

### Accepts

`accept` 속성을 이용해 특정 파일 형식만 업로드할 수 있도록 제한할 수 있습니다.\
파일 확장자 제한을 위한 `accept`값은 필수적으로 받고 있으며, 확장자를 특정해서 사용하거나(`.png,.jpeg,.txt`) `image/*`, `video/*`, `audio/*`와 같은 값을 사용할 수 있습니다.

일부 디바이스에선 MIME type을 사용해서 받을 파일을 제한하는 것이 의도와 다른 동작을 일으킬 수 있기 때문에 `image/*`, `video/*`, `audio/*`를 사용하면 내부적으로 특정 확장자 집합과 맵핑됩니다.

`image/*` = `.jpeg,.jpg,.png,.gif,.bmp,.tiff,.svg,.webp,.heic,.ico`\
`video/*` = `.mp4,.avi,.mkv,.mov,.wmv,.flv,.webm,.mpeg,.3gp,.m4v`\
`audio/*` = `.mp3,.wav,.flac,.aac,.ogg,.m4a,.wma,.aiff,.alac,.midi,.mp4`

```tsx
<Uploader
  accept="image/png, image/jpeg, .pdf,.word,.txt,.doc,.docx"
  maxFileTotalSize={31457280}
/>
```

### File Size

#### Total File Size

`maxFileTotalSize`값으로 업로드 가능한 파일의 총 크기를 제한할 수 있습니다. `maxFileTotalSize`는 필수 속성 값입니다.\
아래의 상황에서 1MB 이상으로 파일을 업로드 해보세요.

```tsx
<Uploader
  accept=".png"
  maxFileTotalSize={1048576}
  label="Click to Upload or drag file"
  size="sm"
/>
```

#### Indivisual File Size

`maxFileSize`값으로 파일 하나의 최대 크기를 제한할 수 있습니다.\
아래의 상황에서 Total 1MB 이상의 파일도 업로드 해보고, 1MB가 넘는 단일 파일도 업로드 해보세요.

```tsx
<Uploader
  accept="image/*, .txt"
  maxFileTotalSize={31457280}
  label="Click to Upload or drag file"
  size="sm"
  maxFileSize={1048576}
/>
```

## Error State

### External Error

`error` prop을 통해 외부에서 에러 상태를 제어할 수 있습니다. 에러 상태일 때 Uploader의 드롭존 테두리가 빨간색으로 변경됩니다.

```tsx
<Uploader
  accept=".png"
  maxFileTotalSize={31457280}
  label="Click to Upload or drag file"
  error
  helperText="This is an error state with custom helper text"
/>
```

### Validation Errors

다양한 검증 규칙을 위반했을 때 자동으로 발생하는 에러들을 확인해보세요:

```tsx
<Stack gap={4}>
  <Stack gap={2}>
    <Typography level="title-sm">Try uploading files that violate validation rules:</Typography>
    <Typography level="body-sm">• Upload a file larger than 500KB (individual file size limit)</Typography>
    <Typography level="body-sm">• Upload multiple files exceeding 1MB total</Typography>
    <Typography level="body-sm">• Upload more than 2 files</Typography>
    <Typography level="body-sm">• Upload non-PNG/JPG files</Typography>
  </Stack>
  <Uploader {...args} />
</Stack>
```

## Helper Text

### Custom Helper Text

`helperText` prop을 사용하면 기본 안내 메시지 대신 사용자 정의 메시지를 표시할 수 있습니다.\
`helperText`가 제공되면 모든 기본 안내 메시지와 에러 메시지보다 우선적으로 표시됩니다.

```tsx
<Stack gap={4}>
  <Stack gap={2}>
    <Typography level="title-sm">Default Helper Text (Generated)</Typography>
    <Uploader {...args} label="Default helper text" accept=".png,.jpg,.pdf" maxFileTotalSize={5 * 1024 * 1024} maxCount={3} />
  </Stack>
  <Stack gap={2}>
    <Typography level="title-sm">Custom Helper Text</Typography>
    <Uploader {...args} label="Custom helper text" accept=".png,.jpg,.pdf" maxFileTotalSize={5 * 1024 * 1024} maxCount={3} helperText="Please upload your profile documents (PNG, JPG, or PDF only)" />
  </Stack>
  <Stack gap={2}>
    <Typography level="title-sm">Error State with Custom Helper Text</Typography>
    <Uploader {...args} label="Error state" accept=".png,.jpg,.pdf" maxFileTotalSize={5 * 1024 * 1024} maxCount={3} error={true} helperText="There was an error processing your files. Please try again." />
  </Stack>
</Stack>
```

## Validation

Uploader 컴포넌트는 다양한 내부 검증 기능을 제공하며, 검증 실패 시 자동으로 에러 메시지를 표시합니다.

### Error Messages

내부 검증에서 발생하는 에러 메시지들:

- **파일 타입 오류**: "Please upload the correct file type."
- **파일 크기 초과**: "One or more files exceeded the maximum file size. Each file size must be \[크기] or less."
- **총 파일 크기 초과**: "The total file size exceeds the maximum limit."
- **파일 개수 초과**: "Exceeded the maximum number of files."
- **최소 파일 개수 미달**: "Please choose \[개수] files to upload." (form validation 시)

### Helper Text Generation

`helperText` prop이 제공되지 않으면 다음 정보를 기반으로 자동 생성됩니다:

1. **허용 파일 타입**: `accept` prop 기반
   - `image/*`, `video/*`, `audio/*` → "Any image file", "Any video file", "Any audio file"
   - 특정 확장자 → 대문자 확장자명 나열
2. **최대 파일 크기**: `maxFileTotalSize` prop 기반
3. **파일 개수 제한**: `maxCount` prop 기반 (있는 경우)

**예시**: "PNG, Maximum 30MB, Up to 3 files"
