# InputMask

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

Diretiva que aplica máscara de entrada em qualquer `<input type="text">`, guiando a digitação conforme um padrão definido. Integra nativamente com Angular Forms via `ControlValueAccessor` e adiciona validação automática de máscara incompleta via `Validator`.

## Quando usar

- Campos com formato fixo: CPF, CNPJ, telefone, data, placa de veículo
- Formulários que exigem validação de preenchimento completo da máscara
- Quando o valor armazenado no model deve ser sem formatação (`unmask: true`)
- Campos com parte opcional na máscara, como telefone fixo ou celular

## Quando não usar

- Para formatação de valores numéricos com separadores de milhar e decimal — use [`NumericMask`](../numeric-mask/README.md)
- Para campos de data integrados ao `p-calendar` — use [`CalendarMask`](../calendar-mask/README.md)
- Quando a entrada é completamente livre sem padrão — não há necessidade de máscara

## Instalação

```typescript
import { InputMaskDirective } from '@seniorsistemas/angular-components/input-mask';

@Component({
    standalone: true,
    imports: [InputMaskDirective, ReactiveFormsModule],
})
export class MeuComponent {
    control = new FormControl('');
}
```

## Uso básico

```html
<input type="text" [sInputMask]="'999.999.999-99'" [formControl]="control" />
```

## API

### Inputs

| Propriedade | Tipo | Padrão | Obrigatório | Descrição |
|-------------|------|--------|:-----------:|-----------|
| `sInputMask` | `string \| undefined` | `undefined` | Sim | Padrão da máscara. Slots: `9` (dígito), `a` (letra), `*` (alfanumérico), `?` (restante opcional). Demais caracteres são literais |
| `slotChar` | `string` | `'_'` | Não | Caractere exibido nas posições ainda não preenchidas |
| `unmask` | `boolean` | `false` | Não | Quando `true`, o model recebe apenas os caracteres digitados, sem os literais da máscara |
| `characterPattern` | `string` | `'[A-Za-z]'` | Não | Expressão regular para validar o slot `a` (letra) |
| `autoClear` | `boolean` | `true` | Não | Limpa o campo ao perder o foco se a máscara estiver incompleta |

### Outputs

| Evento | Tipo | Descrição |
|--------|------|-----------|
| `maskComplete` | `OutputEmitterRef<string>` | Emitido quando todos os slots obrigatórios são preenchidos. Emite o valor atual (mascarado ou não, conforme `unmask`) |

### Slots da máscara

| Caractere | Aceita |
|-----------|--------|
| `9` | Dígito (0–9) |
| `a` | Letra (controlado por `characterPattern`, padrão `[A-Za-z]`) |
| `*` | Alfanumérico (letra ou dígito) |
| `?` | Tudo após esse ponto é opcional |
| Outros | Tratados como literais (ex: `.`, `-`, `/`, `(`, `)`) |

### Validação

A diretiva implementa `Validator` e adiciona o seguinte erro ao `FormControl` quando a máscara está incompleta:

```typescript
{ incompleteMask: { mask: string } }
```

O erro é removido automaticamente quando o campo é preenchido por completo.

## Exemplos

### CPF

```html
<input type="text" [sInputMask]="'999.999.999-99'" [formControl]="cpf" />
```

### CNPJ alfanumérico (a partir de jul/2026)

```html
<!-- Base e ordem alfanuméricos; dígitos verificadores permanecem numéricos -->
<input
    type="text"
    [sInputMask]="'**.***.***/****.99'"
    style="text-transform: uppercase"
    [formControl]="cnpj"
/>
```

### Telefone com unmask

```html
<!-- Model recebe apenas os dígitos: "11999998888" -->
<input
    type="text"
    [sInputMask]="'(99) 99999-9999'"
    [unmask]="true"
    [formControl]="telefone"
/>
```

### Telefone fixo ou celular (slot opcional)

```html
<!-- Aceita 8 ou 9 dígitos após o DDD -->
<input
    type="text"
    [sInputMask]="'(99) 9999?9-9999'"
    [autoClear]="false"
    [formControl]="telefone"
/>
```

### Placa de veículo Mercosul

```html
<!-- 3 letras, 1 dígito, 1 alfanumérico, 2 dígitos -->
<input
    type="text"
    [sInputMask]="'aaa-9*99'"
    style="text-transform: uppercase"
    [formControl]="placa"
/>
```

### Reação ao preenchimento completo

```html
<input
    type="text"
    [sInputMask]="'999.999.999-99'"
    [formControl]="cpf"
    (maskComplete)="onCpfCompleto($event)"
/>
```

```typescript
onCpfCompleto(valor: string): void {
    // valor = '123.456.789-01' (ou só dígitos se unmask=true)
    this.validarCpf(valor);
}
```

### Valor pré-preenchido via model

A diretiva aceita tanto o valor mascarado quanto apenas os dígitos:

```typescript
// Ambos resultam em '123.456.789-01' exibido no campo
control = new FormControl('123.456.789-01');
control = new FormControl('12345678901');
```

### Somente letras maiúsculas no slot `a`

```html
<input
    type="text"
    [sInputMask]="'aaa-9999'"
    characterPattern="[A-Z]"
    [formControl]="codigo"
/>
```

## Acessibilidade

- Navegação por `ArrowLeft`, `ArrowRight`, `Home` e `End` é tratada nativamente pelo browser
- `Tab` e atalhos de teclado (`Ctrl`/`Cmd`) não são interceptados pela diretiva
- Paste com `Ctrl+V` é suportado — a diretiva distribui os caracteres colados nos slots válidos
- Use `text-transform: uppercase` via CSS quando a máscara exigir letras maiúsculas, pois a diretiva não converte caixa automaticamente

## Componentes relacionados

- [`CalendarMask`](../calendar-mask/README.md) — máscara para campos de data integrados ao `p-calendar`
- [`NumericMask`](../numeric-mask/README.md) — formatação de valores numéricos com separadores de milhar e decimal
