# IA.md — Guia para IAs (consumidoras) do pacote `eli-vue`

Este arquivo existe para **IAs e automações** que precisam **importar e usar** o pacote `eli-vue` em projetos Vue 3.

> Fonte da verdade das regras internas do repositório: **`.agent`**.
> Este `IA.md` é focado no **uso do pacote como dependência** (projeto consumidor).

---

## O que é o `eli-vue`

Biblioteca (Design System) de componentes para **Vue 3** com **TypeScript** e integração com **Vuetify 3**.

### Premissas importantes

- O `eli-vue` **não cria** nem configura Vuetify no seu projeto.
- `vue` e `vuetify` são **peerDependencies**: o projeto consumidor precisa ter ambos instalados.
- O pacote utiliza internamente **lucide-vue-next** para ícones.

---

## Instalação (projeto consumidor)

> Preferência do repo: `pnpm`.

```bash
pnpm add eli-vue
```

Se o projeto ainda não tiver as peer dependencies, instale também:

```bash
pnpm add vue vuetify lucide-vue-next
```

> Nota: `lucide-vue-next` é recomendado para passar ícones compatíveis aos componentes (como `EliTabela`).

---

## Uso recomendado

### 1) Registro global via plugin (recomendado)

```ts
import { createApp } from "vue";
import App from "./App.vue";

// Vuetify
import "vuetify/styles";
import { createVuetify } from "vuetify";

// eli-vue
import EliVue from "eli-vue";
// eli-vue
import EliVue from "eli-vue";

const vuetify = createVuetify({});

createApp(App)
  .use(vuetify)
  .use(EliVue)
  .mount("#app");
```

> **Nota**: O CSS é **injetado automaticamente** no bundle JavaScript. Não é necessário importar arquivos `.css` manualmente.


### 2) Importação direta (quando não quiser plugin)

```ts
import {
  EliBotao,
  EliBadge,
  EliCartao,
  EliTabela,
  EliEntradaTexto,
  EliEntradaNumero,
  EliEntradaDataHora,
  EliEntradaParagrafo,
  EliEntradaSelecao,
} from "eli-vue";
```

---

## Tipagem e Helpers

O pacote exporta tipos e funções utilitárias essenciais para o desenvolvimento com TypeScript.

```ts
import { 
  // Componentes
  EliTabela,
  
  // Helpers
  celulaTabela, 
  
  // Tipos
  tipoEliTabelaConsulta, 
  tipoEliColuna,
  tipoEliTabelaAcao,
  CartaoStatus // Tipos compartilhados
} from "eli-vue";
```

---

## Exemplos mínimos

### Botão

```vue
<template>
  <EliBotao @click="salvar">Salvar</EliBotao>
</template>
```

### Entradas (EliEntrada*) com v-model

O `eli-vue` usa uma família de componentes `EliEntrada*` (em vez do antigo `EliInput`).

#### Texto

```vue
<template>
  <EliEntradaTexto
    v-model:value="nome"
    :opcoes="{ rotulo: 'Nome', placeholder: 'Digite seu nome' }"
  />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const nome = ref<string | null>("");
    return { nome };
  },
});
</script>
```

#### Parágrafo (textarea)

```vue
<template>
  <EliEntradaParagrafo
    v-model:value="descricao"
    :opcoes="{ rotulo: 'Descrição', placeholder: 'Digite...', linhas: 5 }"
  />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const descricao = ref<string | null>("");
    return { descricao };
  },
});
</script>
```

#### Seleção (select)

```vue
<template>
  <EliEntradaSelecao
    v-model:value="categoria"
    :opcoes="{
      rotulo: 'Categoria',
      placeholder: 'Selecione...',
      itens: async () => [
        { chave: 'a', rotulo: 'Categoria A' },
        { chave: 'b', rotulo: 'Categoria B' },
      ],
    }"
  />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const categoria = ref<string | null>(null);
    return { categoria };
  },
});
</script>
```

#### Texto com formato/máscara

> Regra importante: o `value` emitido é **sempre o texto formatado** (igual ao que aparece no input).

```vue
<template>
  <EliEntradaTexto
    v-model:value="documento"
    :opcoes="{ rotulo: 'CPF/CNPJ', formato: 'cpfCnpj' }"
  />

  <EliEntradaTexto
    v-model:value="telefone"
    :opcoes="{ rotulo: 'Telefone', formato: 'telefone' }"
  />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
  setup() {
    const documento = ref<string | null>("");
    const telefone = ref<string | null>("");
    return { documento, telefone };
  },
});
</script>
```

### Data e hora (entrada) com suporte a UTC/Z

```vue
<template>
  <!-- Valor chega do backend em ISO 8601 (UTC/offset), e o componente exibe em horário local -->
  <EliEntradaDataHora v-model:value="dataHora" :opcoes="{ rotulo: 'Agendamento' }" />

  <!-- Somente data -->
  <EliEntradaDataHora v-model:value="data" :opcoes="{ rotulo: 'Nascimento', modo: 'data' }" />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    // Exemplo de valor ISO vindo do backend/banco
    const dataHora = ref<string | null>("2026-01-09T16:15:00Z");
    const data = ref<string | null>("2026-01-09T00:00:00-03:00");
    return { dataHora, data };
  },
});
</script>
```

---

## Outros Componentes

### EliBadge (Indicador)

Badge aprimorado que suporta raios predefinidos ("suave" | "pill").

```vue
<template>
  <EliBadge :badge="3" color="error" radius="pill">
    <v-icon>mdi-bell</v-icon>
  </EliBadge>
</template>
```

### EliCartao

Cartão padronizado para representar itens de domínio (ex: propostas) com status coloridos automaticamente.

> **Importante**: O status deve ser um dos valores do tipo `CartaoStatus` ("novo" | "rascunho" | "vendido" | "cancelado").

```vue
<template>
  <EliCartao
    titulo="Proposta #123"
    status="novo" 
    variant="outlined"
  >
    <!-- Conteúdo principal (default slot) -->
    <div class="text-body-2">Cliente: ACME Corp</div>
    <div class="text-caption text-medium-emphasis">Criado há 2 dias</div>

    <!-- Ações (slot 'acoes') -->
    <template #acoes>
      <EliBotao variant="text" size="small">Ver detalhes</EliBotao>
    </template>
  </EliCartao>
</template>

<script lang="ts">
import { defineComponent } from "vue";
// O tipo CartaoStatus é exportado para ajudar na tipagem
import type { CartaoStatus } from "eli-vue";

export default defineComponent({
  setup() {
    const statusAtual: CartaoStatus = "novo";
    return { statusAtual };
  }
});
</script>
```

---

## EliTabela (Tabela Avançada)

O componente `EliTabela` suporta ordenação, paginação, busca e **filtro avançado**. 
Para type-safety, recomenda-se definir a estrutura da consulta usando `tipoEliTabelaConsulta<T>`.

### Barra de Busca e Filtros

O `EliTabela` oferece duas formas principais de filtrar dados:
1. **Busca Textual Simples**: Uma caixa de busca global.
2. **Filtro Avançado**: Um modal para composição de filtros específicos por coluna.

#### 1. Busca Textual Simples

Para habilitar, defina `mostrarCaixaDeBusca: true`.
O termo digitado será passado para a função `consulta` no parâmetro `texto_busca`.

```ts
mostrarCaixaDeBusca: true,
consulta: async ({ texto_busca }) => {
  // Use 'texto_busca' para filtrar no backend (ex: ILIKE %texto%)
}
```

#### 2. Filtro Avançado

Permite que o usuário crie filtros complexos (ex: "Data > X" E "Status = Y").
Você define os campos disponíveis em `filtroAvancado`.

Cada definição de filtro precisa de:
- `rotulo`: Nome exibido ao usuário.
- `coluna`: Chave do dado (`keyof T`) a ser filtrada.
- `operador`: Operação padrão (ex: `like`, `=`, `>`, `<`, `>=`, `<=`, `!=`, `in`, `between`).
- `entrada`: Definição do componente de entrada (`EliEntrada*`) usado para capturar o valor.

> **Dica de Tipagem**: O campo `entrada` espera uma tupla `[Tipo, Opcoes]`. Devido à complexidade do TypeScript, pode ser necessário usar `as any` ou castar para `ComponenteEntrada`.

```ts
filtroAvancado: [
  {
    rotulo: "Nome do Cliente",
    coluna: "nome", // chave em T
    operador: "like",
    // Configuração do input (igual ao usar EliEntradaTexto)
    entrada: ["texto", { rotulo: "Digite o nome", placeholder: "Ex: João" }] as any, 
  },
  {
    rotulo: "Data de Criação",
    coluna: "criado_em",
    operador: ">=",
    // Configuração do input (EliEntradaDataHora)
    entrada: ["dataHora", { rotulo: "A partir de", modo: "data" }] as any,
  },
  {
    rotulo: "Status",
    coluna: "status",
    operador: "=",
    // Configuração do input com seleção
    entrada: ["selecao", {
      rotulo: "Selecione",
      itens: () => [
        { chave: "ativo", rotulo: "Ativo" },
        { chave: "inativo", rotulo: "Inativo" }
      ]
    }] as any
  }
]
```

### Processando a Consulta

A função `consulta` recebe um objeto com todos os parâmetros necessários para buscar os dados corretamente.

```ts
consulta: async (params) => {
  const { 
    offSet,          // Paginação: pular N registros
    limit,           // Paginação: limite por página
    texto_busca,     // Busca simples (string | undefined)
    coluna_ordem,    // Ordenação: qual coluna
    direcao_ordem,   // Ordenação: "asc" | "desc"
    filtros          // Array de filtros aplicados pelo usuário
  } = params;
  
  // Exemplo de estrutura de 'filtros':
  // [
  //   { coluna: "nome", operador: "like", valor: "Ana" },
  //   { coluna: "criado_em", operador: ">=", valor: "2024-01-01" }
  // ]

  console.log("Buscando dados...", params);

  // ... chamada à API ...
  
  return {
    cod: 0,
    eCerto: true,
    eErro: false,
    mensagem: undefined,
    valor: { 
      // Retorne SEMPRE o total real de registros para a paginação funcionar
      quantidade: 100, 
      valores: [ /* ... array de T ... */ ] 
    },
  };
},
```

### Exemplo Completo Tipado

```ts
import { defineComponent } from "vue";
import { EliTabela, celulaTabela } from "eli-vue";
import type { tipoEliTabelaConsulta } from "eli-vue";
// Tipos auxiliares (opcionais, mas úteis)
import { BadgeCheck, Pencil } from "lucide-vue-next";

// 1. Defina o tipo da linha
type Usuario = { 
  id: number; 
  nome: string; 
  documento: string; 
  email: string; 
  ativo: boolean;
  criado_em: string; 
};

// 2. Defina a configuração da tabela
const tabelaUsuarios: tipoEliTabelaConsulta<Usuario> = {
  nome: "Usuarios",
  mostrarCaixaDeBusca: true,
  registros_por_consulta: 10,
  
  // Colunas Visuais
  colunas: [
    { 
      rotulo: "Nome", 
      celula: (row) => celulaTabela("textoSimples", { texto: row.nome }), 
      visivel: true,
      coluna_ordem: "nome" // Habilita ordenação por esta coluna
    },
    {
      rotulo: "Status",
      visivel: true,
      celula: (row) => celulaTabela("tags", {
        opcoes: [
          row.ativo 
            ? { rotulo: "Ativo", cor: "success", icone: BadgeCheck }
            : { rotulo: "Inativo", cor: "error" }
        ]
      })
    },
    {
      rotulo: "Criado em",
      visivel: true,
      celula: (row) => celulaTabela("data", {
        valor: row.criado_em,
        formato: "data_hora"
      })
    }
  ],

  // Ações de linha (botões à direita)
  acoesLinha: [
    {
      rotulo: "Editar",
      icone: Pencil,
      cor: "primary",
      acao: (row) => console.log("Editar", row.id)
    }
  ],

  // Definição dos Filtros Avançados disponíveis
  filtroAvancado: [
    {
      rotulo: "Documento",
      coluna: "documento",
      operador: "like",
      entrada: ["texto", { rotulo: "Documento", formato: "cpfCnpj" }] as any,
    },
    {
      rotulo: "Criado em (Início)",
      coluna: "criado_em",
      operador: ">=",
      entrada: ["dataHora", { rotulo: "A partir de", modo: "data" }] as any
    }
  ],

  // Função de consulta
  consulta: async (params) => {
    // Aqui você conectaria com sua API, passando params.filtros, params.texto_busca, etc.
    console.log("Filtros aplicados:", params.filtros);
     
    return {
      cod: 0,
      eCerto: true,
      eErro: false,
      mensagem: undefined,
      valor: { 
        quantidade: 1, 
        valores: [
          { id: 1, nome: "Luiz", documento: "123", email: "a@a.com", ativo: true, criado_em: "2024-01-01" }
        ] 
      },
    };
  },
};
```

### Tipos de Células (`celulaTabela`)

Helper: `celulaTabela(tipo, dados)`

- `textoSimples`: `{ texto: string; acao?: () => void }`
- `textoTruncado`: `{ texto: string; acao?: () => void }`
- `numero`: `{ numero: number; prefixo?: string; sufixo?: string; acao?: () => void }`
- `tags`: `{ opcoes: { rotulo: string; cor?: string; icone?: LucideIcon; acao?: () => void }[] }`
- `data`: `{ valor: string; formato: "data" | "data_hora" | "relativo"; acao?: () => void }`

---

## Troubleshooting (para IAs)

### 1) “Failed to resolve component”

Provável causa: componente não foi registrado.
- Se estiver usando plugin: confirme `app.use(EliVue)`
- Se estiver importando direto: registre localmente no componente

### 2) Estilos não aplicam ou componentes "quebrados"

**Causa provável**: O CSS não foi injetado corretamente pelo JavaScript.

O `eli-vue` injeta o CSS automaticamente via JS. Verifique se o bundle está sendo carregado corretamente e se não há bloqueios de Content Security Policy (CSP) para injeção de estilos `<style>`.

Anteriormente era necessário importar o CSS manualmente, mas **isso não é mais necessário**.


### 3) Erro de tipo em `celulaTabela`

Verifique se você importou `celulaTabela` de `eli-vue`. 
Certifique-se de que o segundo argumento corresponde ao tipo da célula (ex: `textoSimples` pede `{ texto: string }`).

### 4) Ícones não aparecem

O `eli-vue` espera ícones do pacote `lucide-vue-next` (ou compatíveis com Component type do Vue).
Certifique-se de passar o componente do ícone (ex: `Pencil`), e não string.

---

## Como a IA deve agir ao modificar um projeto consumidor

Quando for integrar `eli-vue` num projeto existente:

1) Verifique se **Vue 3**, **Vuetify 3** e **lucide-vue-next** estão instalados.
2) Prefira usar o **plugin** do `eli-vue` (simplifica registro global).
3) Use `celulaTabela` para construir colunas de tabelas de forma tipada.
5) Ao definir tabelas, use `tipoEliTabelaConsulta<T>` para garantir que colunas e filtros batam com o tipo de dados.

---

## Quando este arquivo deve ser atualizado

Atualize este `IA.md` quando houver mudanças em:
- Estrutura de exports (novos componentes ou helpers).
- Tipagem das células ou entradas.
- Dependências obrigatórias.
