# FileUploader

## Overview

Drag-and-drop uploader with keyboard activation, file type filtering, limits (count/total size), previews via `FilePreview`, and external upload integration.

---

## Props

| Prop                | Type                      | Default                                            | Description                                               |
| ------------------- | ------------------------- | -------------------------------------------------- | --------------------------------------------------------- |
| `extensions`        | `AcceptItem[]`            | `["pdf","image","video","audio"]`                  | Allowed extensions/categories (maps to accept attribute). |
| `multiple`          | `boolean`                 | `false`                                            | Enables multiple file selection.                          |
| `onUpload`          | `(files: File[]) => void` | `undefined`                                        | Called when files are **added**, with the resulting list. |
| `onRemove`          | `(removed: File[], remaining: File[]) => void` | `undefined`                           | Called when files are **removed** (single or remove-all), with the removed files and the list that remains. |
| `description`       | `string`                  | `"Trascina un file o clicca per selezionare"`      | Dropzone hint.                                            |
| `formatDescription` | `string`                  | `"Formato accettato: PDF, Immagini, Video, Audio"` | Accepted formats hint.                                    |
| `selectedLabel`     | `string`                  | `"File selezionati"`                               | Title shown above selected files list.                    |
| `removeAllLabel`    | `string`                  | `"rimuovi tutto"`                                  | Label for the "remove all" button.                        |
| `maxTotalSize`      | `number` (bytes)          | `undefined`                                        | Maximum total size of selected files.                     |
| `maxFiles`          | `number`                  | `undefined`                                        | Maximum number of files (when `multiple` is true).        |

`AcceptItem` includes: `pdf | doc | docx | xls | xlsx | ppt | pptx | txt | csv | jpg | jpeg | png | gif | image | video | audio | zip | rar | 7z | tar | gz | tgz`.

---

## Behavior

- **Dropzone**: Click or drag files; keyboard accessible (Enter/Space opens file dialog).
- **Filtering**: `extensions` map to accept string; only matching files are added.
- **Limits**: Enforces `maxFiles` and `maxTotalSize` (with compact error caption).
- **Previews**: Renders selected files with `FilePreview`; supports remove per file and remove-all.
- **Integration**: `onUpload` fires on **add** with the resulting `File[]`; `onRemove` fires on **removal** (single file or remove-all) with the removed files and the remaining list. Removals do **not** trigger `onUpload` — a consumer mirroring the list in its own state must handle both callbacks (see example below).

---

## Examples

### Default

```tsx
import { FileUploader } from "laif-ds";

export function DefaultUploader() {
  return <FileUploader multiple={false} />;
}
```

### Multiple + Custom Extensions

```tsx
import { FileUploader, type AcceptItem } from "laif-ds";

const exts: AcceptItem[] = [
  "pdf",
  "doc",
  "docx",
  "xls",
  "xlsx",
  "ppt",
  "pptx",
  "txt",
  "csv",
  "jpg",
  "jpeg",
  "png",
  "gif",
  "image",
  "video",
  "audio",
  "zip",
  "rar",
  "7z",
  "tar",
  "gz",
  "tgz",
];

export function MultiUploader() {
  return (
    <FileUploader
      multiple
      extensions={exts}
      description="Seleziona più file"
      formatDescription="Trascina o clicca per selezionare più file"
    />
  );
}
```

### With Limits

```tsx
import { FileUploader } from "laif-ds";

export function LimitedUploader() {
  return (
    <FileUploader
      multiple
      maxFiles={3}
      maxTotalSize={10 * 1024 * 1024} // 10 MB
      description="Con limiti su numero e dimensione totale"
      formatDescription="Esempio: max 3 file, max totale 10 MB"
    />
  );
}
```

### External Upload Flow

```tsx
import * as React from "react";
import { Button } from "laif-ds";
import { FileUploader } from "laif-ds";

export function ExternalUploadExample() {
  const [files, setFiles] = React.useState<File[]>([]);
  const [loading, setLoading] = React.useState(false);

  const handleSubmit = async () => {
    setLoading(true);
    // ...upload files
    await new Promise((r) => setTimeout(r, 1500));
    setLoading(false);
    alert(`Upload completato: ${files.length} file`);
  };

  return (
    <div className="space-y-4">
      <FileUploader
        multiple
        onUpload={setFiles}
        onRemove={(_removed, remaining) => setFiles(remaining)}
      />
      {files.length > 0 && (
        <div className="flex justify-end">
          <Button onClick={handleSubmit} isLoading={loading} iconLeft="Upload">
            {loading ? "Caricamento..." : `Carica ${files.length} file`}
          </Button>
        </div>
      )}
    </div>
  );
}
```

---

## Notes

- **A11y**: Dropzone is a button-like region with `aria-describedby` hints and keyboard support.
- **Errors**: Limit violations are summarized in a compact caption.
- **Localization**: Provide localized `description`/`formatDescription`/labels when needed.
