# File Upload

> Drag-and-drop file uploader with preview, progress, and validation hooks.

- Package: `@sisyphos-ui/file-upload`
- Docs: https://sisyphosui.com/docs/components/file-upload
- npm: https://www.npmjs.com/package/@sisyphos-ui/file-upload

## Installation

```bash
pnpm add @sisyphos-ui/file-upload @sisyphos-ui/core
```

Or use the umbrella package:

```bash
pnpm add @sisyphos-ui/ui
```

## Import

```tsx
import "@sisyphos-ui/file-upload/styles.css";
import { FileUpload } from "@sisyphos-ui/file-upload";
```

## Examples

### Default

Always controlled — parent owns the list of files via `value`/`onChange`.

```tsx
import { useState } from "react";
import { FileUpload, type UploadedFile } from "@sisyphos-ui/ui";

export function Example() {
  const [files, setFiles] = useState<UploadedFile[]>([]);

  return (
    <div className="w-full max-w-md">
      <FileUpload
        value={files}
        onChange={setFiles}
        accept="image/*"
        multiple
        maxFiles={3}
        supportedFormats={["PNG", "JPG", "WEBP"]}
      />
    </div>
  );
}
```

### Max size with onReject

`maxSize` enforces a byte limit; `onReject` receives the rejection reason so you can show a friendly message.

```tsx
import { useState } from "react";
import { FileUpload, type UploadedFile } from "@sisyphos-ui/ui";

export function Example() {
  const [files, setFiles] = useState<UploadedFile[]>([]);
  const [message, setMessage] = useState<string | null>(null);

  return (
    <>
      <FileUpload
        label="Attach logo"
        value={files}
        onChange={setFiles}
        accept="image/*"
        maxSize={2 * 1024 * 1024}
        onReject={(file, reason) => {
          if (reason.kind === "size") {
            setMessage(`"${file.name}" is too large.`);
          }
        }}
      />
      {message && <p>{message}</p>}
    </>
  );
}
```

### Error state

Pair `error` with external error messaging for form validation.

```tsx
import { useState } from "react";
import { FileUpload, type UploadedFile } from "@sisyphos-ui/ui";

export function Example() {
  const [files, setFiles] = useState<UploadedFile[]>([]);

  return (
    <>
      <FileUpload label="CV" value={files} onChange={setFiles} error />
      <p>Please attach your CV to continue.</p>
    </>
  );
}
```
