# FilePicker

![Status](https://img.shields.io/badge/status-stable-brightgreen)

Componente de upload de arquivos com suporte a seleção múltipla, validação de tipo e tamanho, controle granular de permissões (adicionar, ler, remover), exibição de progresso e cancelamento de uploads em andamento.

## Quando usar

- Upload de anexos em formulários (documentos, imagens, relatórios)
- Envio de arquivos em processos ou entidades
- Exibição de arquivos já salvos com possibilidade de download e remoção

## Quando não usar

- Upload de foto de perfil com recorte — use [`ProfilePicturePicker`](../profile-picture-picker/README.md)
- O seletor `s-file-upload` e o pacote `file-upload` estão descontinuados (remoção na v20.0.0) — use `s-file-picker`

## Instalação

```typescript
import { FilePickerModule } from '@seniorsistemas/angular-components/file-picker';

@Component({ standalone: true, imports: [FilePickerModule] })
export class MeuComponent {}
```

## Uso básico

```html
<s-file-picker
  [files]="arquivos"
  [multiple]="true"
  (uploadHandler)="onUpload($event)"
  (removeFile)="onRemove($event)"
/>
```

## API

### Inputs

| Propriedade | Tipo | Padrão | Obrigatório | Descrição |
|-------------|------|--------|:-----------:|-----------|
| `files` | `FileDto[]` | — | — | Lista de arquivos já enviados a serem exibidos |
| `multiple` | `boolean` | — | — | Permite selecionar múltiplos arquivos |
| `accept` | `string` | — | — | Tipos MIME aceitos pelo seletor nativo (ex: `'application/pdf,image/*'`) |
| `supportedExtensions` | `string[]` | `[]` | — | Extensões aceitas para validação (ex: `['.pdf', '.docx']`) |
| `maxFileSize` | `number` | — | — | Tamanho máximo por arquivo em bytes |
| `maxCombinedFileSize` | `number` | — | — | Tamanho máximo combinado de todos os arquivos em bytes |
| `fileLimit` | `number` | — | — | Número máximo de arquivos que podem ser selecionados |
| `permissions` | `FilePickerPermissions[]` | `['add', 'read', 'remove']` | — | Permissões habilitadas no componente |
| `disabled` | `boolean` | `false` | — | Desabilita todas as interações do componente |
| `showFileUploadDate` | `boolean` | `false` | — | Exibe a data de upload de cada arquivo |
| `chooseLabel` | `string` | — | — | Rótulo customizado do botão de seleção |
| `removeLabel` | `string` | — | — | Rótulo customizado do link de remoção |
| `cancelLabel` | `string` | — | — | Rótulo customizado do botão de cancelamento |
| `successTooltip` | `string` | — | — | Texto do tooltip após upload bem-sucedido |
| `ariaLabelFileName` | `string` | — | — | Label ARIA para o nome do arquivo |
| `ariaLabelProgress` | `string` | — | — | Label ARIA para a barra de progresso |
| `ariaLabelSuccess` | `string` | — | — | Label ARIA para o ícone de sucesso |
| `ariaLabelError` | `string` | — | — | Label ARIA para mensagens de erro |
| `ariaLabelRemove` | `string` | — | — | Label ARIA para o botão de remoção |
| `formControl` | `FormControl` | — | — | FormControl externo para controle de estado |
| `id` | `string` | `s-file-picker-{n}` | — | Identificador único do componente |

### Outputs

| Evento | Tipo | Descrição |
|--------|------|-----------|
| `uploadHandler` | `EventEmitter<{ files: FileDto[] }>` | Emitido quando arquivos válidos são selecionados para upload |
| `removeFile` | `EventEmitter<{ file: File }>` | Emitido quando um arquivo é removido da lista |
| `cancelUpload` | `EventEmitter<number>` | Emitido ao cancelar um upload em andamento (emite o índice) |
| `downloadFile` | `EventEmitter<{ index: number; anchor: ElementRef }>` | Emitido ao clicar para baixar um arquivo |
| `validateErrors` | `EventEmitter<UploadError>` | Emitido quando um arquivo não passa na validação |

### Tipos

```typescript
type FilePickerPermissions = 'add' | 'read' | 'remove';
// 'add' = exibe o botão de seleção de arquivo
// 'read' = exibe o nome do arquivo como link para download
// 'remove' = exibe o link de remoção

interface FileDto extends File {
  objectId?: string;        // ID do objeto no servidor
  version?: string;         // Versão do arquivo
  objectURL?: string;       // URL para preview/download
  isUploading?: boolean;    // Se está sendo enviado
  savedFile?: boolean;      // Se já foi salvo no servidor
  progress?: number;        // Progresso do upload (0-100)
  error?: HttpErrorResponse;// Erro de upload, se houver
}

interface UploadError {
  files: FileDto[];
  validation: 'maxFileLimit' | 'maxFileSize' | 'maxCombinedFileSize' | 'unsupportedExtension';
}
```

## Exemplos

### Upload básico com múltiplos arquivos

```html
<s-file-picker
  [files]="arquivos"
  [multiple]="true"
  [fileLimit]="5"
  [maxFileSize]="5242880"
  [permissions]="['add', 'read', 'remove']"
  (uploadHandler)="onUpload($event)"
  (removeFile)="onRemove($event)"
  (validateErrors)="onErros($event)"
></s-file-picker>
```

```typescript
arquivos: FileDto[] = [];

onUpload(event: { files: FileDto[] }) {
  event.files.forEach(f => { f.progress = 100; });
  this.arquivos = [...this.arquivos, ...event.files];
}

onRemove(event: { file: FileDto }) {
  this.arquivos = this.arquivos.filter(f => f !== event.file);
}
```

### Somente leitura

```html
<s-file-picker
  [files]="arquivos"
  [permissions]="['read']"
></s-file-picker>
```

### Com filtro de extensões

```html
<s-file-picker
  [files]="arquivos"
  accept=".pdf,.docx"
  [supportedExtensions]="['.pdf', '.docx']"
  [multiple]="true"
  [fileLimit]="3"
  (uploadHandler)="onUpload($event)"
  (validateErrors)="onErros($event)"
></s-file-picker>
```

## Acessibilidade

- O botão de seleção de arquivo ativa o seletor nativo do sistema operacional
- A barra de progresso possui `aria-label` configurável via `ariaLabelProgress`
- O nome do arquivo exibido é associado ao `ariaLabelFileName` para leitores de tela
- Drag and drop é suportado como alternativa ao clique

## Componentes relacionados

- [`ProfilePicturePicker`](../profile-picture-picker/README.md) — upload específico para foto de perfil com recorte
