# GlobalSearch

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

Componente de busca global com campo de input, dropdown de resultados animado, estado de carregamento, empty state e suporte a itens customizáveis via `s-global-search-dropdown-item`. Os resultados são projetados via `ng-content`.

## Quando usar

- Busca global na topbar da aplicação para pesquisar entidades (colaboradores, clientes, documentos)
- Pesquisa com resultados em dropdown com link para busca avançada
- Interfaces que precisam de busca rápida com feedback de carregamento e estado vazio

## Quando não usar

- Busca com seleção de valor vinculada a um `FormControl` — use [`Autocomplete`](../autocomplete/README.md)
- Filtros de listagem local — use um campo de texto simples com pipe de filtro

## Instalação

```typescript
import { GlobalSearchModule } from '@seniorsistemas/angular-components/global-search';

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

## Uso básico

```html
<s-global-search
  totalItensLabel="resultados encontrados"
  showMoreLabel="Ver busca avançada"
  [totalElements]="total"
  [isLoading]="carregando"
  (searched)="onSearch($event)"
  (moreShown)="onVerMais()"
>
  @for (item of resultados; track item.id) {
    <s-global-search-dropdown-item
      [primaryLabel]="item.nome"
      [secondaryLabel]="item.cargo"
    ></s-global-search-dropdown-item>
  }
</s-global-search>
```

## API

### Inputs

| Propriedade | Tipo | Padrão | Obrigatório | Descrição |
|-------------|------|--------|:-----------:|-----------|
| `totalItensLabel` | `string` | — | Sim | Label que acompanha o total de resultados no rodapé |
| `showMoreLabel` | `string` | — | Sim | Rótulo do link para exibir mais resultados |
| `placeholder` | `string` | — | — | Placeholder do input de busca |
| `delay` | `number` | `500` | — | Tempo de debounce em ms antes de emitir o evento de busca |
| `isLoading` | `boolean` | `false` | — | Exibe indicador de carregamento no dropdown |
| `totalElements` | `number` | — | — | Número total de resultados encontrados |
| `emptyTitle` | `string` | — | — | Título do empty state quando não há resultados |
| `emptyDescription` | `string` | — | — | Descrição do empty state exibida abaixo do título |
| `emptyIcon` | `string` | — | — | Classe do ícone exibido no empty state |
| `showFooter` | `boolean` | `true` | — | Exibe o rodapé com link "ver mais" e contagem de resultados |
| `id` | `string` | `s-global-search-{n}` | — | Identificador único do componente |

### Outputs

| Evento | Tipo | Descrição |
|--------|------|-----------|
| `searched` | `EventEmitter<string>` | Emitido ao digitar no campo (com debounce), com o valor atual |
| `focused` | `EventEmitter<boolean>` | Emitido quando o campo ganha (`true`) ou perde (`false`) foco |
| `moreShown` | `EventEmitter<void>` | Emitido ao clicar no link para exibir mais resultados |

## Exemplos

### Busca com resultados dinâmicos

```html
<s-global-search
  totalItensLabel="colaboradores encontrados"
  showMoreLabel="Ver busca avançada"
  [totalElements]="resultados.length"
  [isLoading]="carregando"
  placeholder="Buscar colaborador..."
  emptyTitle="Nenhum resultado encontrado"
  emptyDescription="Tente buscar por outro termo"
  emptyIcon="fa fa-search"
  (searched)="onSearch($event)"
  (moreShown)="irParaBuscaAvancada()"
>
  @for (item of resultados; track item.id) {
    <s-global-search-dropdown-item
      [primaryLabel]="item.nome"
      [secondaryLabel]="item.cargo"
      [tertiaryLabel]="item.departamento"
      iconClass="far fa-user"
      size="standart"
    ></s-global-search-dropdown-item>
  }
</s-global-search>
```

```typescript
resultados: any[] = [];
carregando = false;

onSearch(query: string) {
  if (!query) { this.resultados = []; return; }
  this.carregando = true;
  this.searchService.buscar(query).subscribe(data => {
    this.resultados = data;
    this.carregando = false;
  });
}
```

### Sem rodapé

```html
<s-global-search
  totalItensLabel="itens"
  showMoreLabel="Ver mais"
  [showFooter]="false"
  (searched)="onSearch($event)"
>
  <!-- itens -->
</s-global-search>
```

### s-global-search-dropdown-item

Campos do componente de item de resultado:

| Propriedade | Tipo | Descrição |
|-------------|------|-----------|
| `id` | `string` | Identificador único do item. Gerado automaticamente quando omitido |
| `primaryLabel` | `string` | Texto principal do item (obrigatório) |
| `secondaryLabel` | `string` | Texto secundário |
| `secondaryEmptyLabel` | `string` | Texto exibido no lugar de `secondaryLabel` quando este está vazio |
| `tertiaryLabel` | `string` | Texto terciário |
| `tertiaryEmptyLabel` | `string` | Texto exibido no lugar de `tertiaryLabel` quando este está vazio |
| `iconClass` | `string` | Classe de ícone Font Awesome |
| `imageSource` | `string` | URL de imagem (thumbnail) |
| `imageAlt` | `string` | Texto alternativo da imagem/thumbnail. Usa `primaryLabel` quando omitido |
| `size` | `'standart' \| 'medium' \| 'small'` | Tamanho do item |
| `template` | `TemplateRef<any>` | Template customizado exibido ao lado do item (área de 40% de largura) |

**Outputs:**

| Evento | Tipo | Descrição |
|--------|------|-----------|
| `buttonClick` | `EventEmitter<void>` | Emitido ao clicar no botão de `primaryLabel` do item |

## Acessibilidade

- O campo de busca possui suporte a `placeholder` e pode receber `aria-label` via configuração
- O dropdown abre automaticamente ao digitar e fecha ao limpar o campo
- Os itens do dropdown são elementos clicáveis com rótulo visível via `primaryLabel`

## Componentes relacionados

- [`Autocomplete`](../autocomplete/README.md) — busca com seleção de valor vinculada a formulário
- [`Topbar`](../topbar/src/lib/topbar/README.md) — barra superior onde o GlobalSearch é tipicamente posicionado
