vue-componentes/IA.md
2026-01-29 18:31:52 -03:00

8.4 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. 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.

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

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";

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 value emitido é 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() {
    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>

EliTabela (com filtro avançado)

O componente EliTabela suporta:

  • ordenação
  • paginação
  • caixa de busca
  • filtro avançado (modal)

Contrato da tabela (resumo)

O tipo principal é EliTabelaConsulta<T> (genérico), exportado de eli-vue.

O filtroAvancado é uma lista de filtros pré-definidos (o usuário só escolhe quais usar e informa valores):

filtroAvancado?: {
  rotulo: string
  coluna: keyof T
  operador: string // ex.: "like", "=", ">", "in", "isNull"
  entrada: ["texto" | "numero" | "dataHora", { rotulo: string; ... }]
}[]

Exemplo mínimo

import { EliTabela, celulaTabela } from "eli-vue";
import type { EliTabelaConsulta } from "eli-vue";
import type { ComponenteEntrada } from "eli-vue/dist/types/componentes/EliEntrada/tiposEntradas";

type Linha = { nome: string; documento: string; email: string };

const tabela: EliTabelaConsulta<Linha> = {
  nome: "Exemplo",
  mostrarCaixaDeBusca: true,
  registros_por_consulta: 10,
  colunas: [
    { rotulo: "Nome", celula: (l) => celulaTabela("textoSimples", { texto: l.nome }), visivel: true },
  ],
  filtroAvancado: [
    {
      rotulo: "Documento",
      coluna: "documento",
      operador: "like",
      entrada: ["texto", { rotulo: "Documento", formato: "cpfCnpj" }] as unknown as ComponenteEntrada,
    },
  ],
  consulta: async () => ({
    cod: 0,
    eCerto: true,
    eErro: false,
    mensagem: undefined,
    valor: { quantidade: 0, valores: [] },
  }),
};


Células da EliTabela (celulaTabela)

O eli-vue expõe o helper celulaTabela(tipo, dados) para construir células tipadas.

Tipos disponíveis atualmente:

  • 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 }

Exemplo: célula tags

import { celulaTabela } from "eli-vue";
import { BadgeCheck, Pencil } from "lucide-vue-next";

celula: (l) =>
  celulaTabela("tags", {
    opcoes: [
      { rotulo: "Ativo", cor: "success", icone: BadgeCheck },
      { rotulo: "Editar", cor: "primary", icone: Pencil, acao: () => editar(l) },
    ],
  })

Exemplo: célula data

import { celulaTabela } from "eli-vue";

celula: (l) =>
  celulaTabela("data", {
    valor: l.criado_em, // ISO
    formato: "data", // "data" | "data_hora" | "relativo"
  })

Observação: em modo simulação/local, a tabela pode buscar uma lista completa e aplicar filtro/paginação localmente.


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/styles
  • eli-vue/dist/eli-vue.css

3) Ícones não aparecem

Alguns exemplos usam <v-icon> (MDI). O eli-vue não instala ícones automaticamente no projeto consumidor.


Como a IA deve agir ao modificar um projeto consumidor

Quando for integrar eli-vue num projeto existente:

  1. Verifique se Vue 3 e Vuetify 3 já estão configurados.
  2. Prefira usar o plugin do eli-vue (simplifica registro).
  3. Garanta o import do CSS do pacote (eli-vue/dist/eli-vue.css).
  4. Ao ver erros de tipos, valide se o projeto está usando TypeScript e se o build está resolvendo types corretamente.

Quando este arquivo deve ser atualizado

Atualize este IA.md quando houver mudanças em qualquer um destes pontos:

  • caminho/nome do CSS em dist/
  • forma de instalação e/ou peerDependencies
  • forma de uso do plugin/export principal
  • lista de exports públicos (novos componentes, renomes, remoções)
  • mudanças de comportamento relevantes para consumo