14 KiB
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. EsteIA.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-vuenão cria nem configura Vuetify no seu projeto. vueevuetifysã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.
pnpm add eli-vue
Se o projeto ainda não tiver as peer dependencies, instale também:
pnpm add vue vuetify lucide-vue-next
Nota:
lucide-vue-nexté recomendado para passar ícones compatíveis aos componentes (comoEliTabela).
Uso recomendado
1) Registro global via plugin (recomendado)
import { createApp } from "vue";
import App from "./App.vue";
// Vuetify
import "vuetify/styles";
import { createVuetify } from "vuetify";
// eli-vue
import EliVue from "eli-vue";
import "eli-vue/dist/eli-vue.css";
const vuetify = createVuetify({});
createApp(App)
.use(vuetify)
.use(EliVue)
.mount("#app");
2) Importação direta (quando não quiser plugin)
import {
EliBotao,
EliBadge,
EliCartao,
EliTabela,
EliEntradaTexto,
EliEntradaNumero,
EliEntradaDataHora,
EliEntradaParagrafo,
EliEntradaSelecao,
} from "eli-vue";
Observação: ainda pode ser necessário importar o CSS do pacote:
import "eli-vue/dist/eli-vue.css";
Tipagem e Helpers
O pacote exporta tipos e funções utilitárias essenciais para o desenvolvimento com TypeScript.
import {
// Componentes
EliTabela,
// Helpers
celulaTabela,
// Tipos
tipoEliTabelaConsulta,
tipoEliColuna,
tipoEliTabelaAcao,
CartaoStatus // Tipos compartilhados
} from "eli-vue";
Exemplos mínimos
Botão
<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
<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)
<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)
<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
valueemitido é sempre o texto formatado (igual ao que aparece no input).
<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
<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").
<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").
<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:
- Busca Textual Simples: Uma caixa de busca global.
- 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.
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
entradaespera uma tupla[Tipo, Opcoes]. Devido à complexidade do TypeScript, pode ser necessário usaras anyou castar paraComponenteEntrada.
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.
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
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
Confirme que o projeto importou:
vuetify/styleseli-vue/dist/eli-vue.css
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:
- Verifique se Vue 3, Vuetify 3 e lucide-vue-next estão instalados.
- Prefira usar o plugin do
eli-vue(simplifica registro global). - Garanta o import do CSS do pacote (
eli-vue/dist/eli-vue.css). - Use
celulaTabelapara construir colunas de tabelas de forma tipada. - 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.