Buscar K
Aparência
Aparência
Um Componente Reutilizável transforma um Widget Svelte em uma peça configurável que passa a aparecer como um novo tipo de widget na biblioteca do Dashboard.
A ideia: quem sabe programar cria o componente uma vez (com o código e um conjunto de opções configuráveis); depois, qualquer pessoa que monta dashboards pode usar e ajustar esse componente sem tocar em código — só preenchendo campos.
TIP
Exemplo: um desenvolvedor cria um "Cartão de Meta" sofisticado e expõe como opções a coluna de valor, a meta e a cor. A partir daí, qualquer usuário adiciona esse cartão em vários dashboards e só escolhe a coluna e a cor — sem ver o código.
A funcionalidade separa claramente quem cria de quem usa:
| Papel | O que faz |
|---|---|
| Autor | Escreve o código, define quais opções ficam configuráveis (o Contrato), define a aparência fixa, e publica o componente. |
| Quem monta dashboards | Escolhe o componente na biblioteca e preenche os campos configuráveis. Não vê nem edita o código. |
Crie um Widget Svelte normalmente. Ele usa o mesmo ambiente (Svelte 4, biblioteca app para dados, Tailwind, etc.).
Em vez de fixar a tabela, a coluna ou os textos diretamente no código, leia tudo das opções configuráveis — assim o mesmo código serve para muitos casos.
No editor, clique em "Transformar em paramétrico" para habilitar o Contrato.
O Contrato é a lista de opções que ficarão disponíveis para quem usar o componente. Cada opção que o seu código lê precisa estar declarada no Contrato (e vice-versa).
Para cada campo você define o rótulo (nome amigável), a chave (como o código o lê) e o tipo. Os tipos disponíveis estão detalhados na referência do Contrato.
TIP
O Contrato pode ser editado de forma visual (campo a campo) ou em JSON (modo avançado), com validação ao vivo.
Você também pode agrupar campos — campos do mesmo grupo aparecem juntos para quem configura.
Na seção "Aparência do widget", o autor decide opções visuais que valem para todas as instâncias:
IMPORTANT
A aparência é fixa pelo autor — quem usa o componente não pode alterá-la. Se você criar um cartão com fundo transparente, todas as instâncias serão transparentes.
Clique em "Salvar como componente", informe nome, ícone e categoria. O widget que você estava editando passa a ser uma instância desse componente, e ele entra na biblioteca.
O componente recebe duas props injetadas pelo Horus:
app — a ponte com os dados e o motor (a mesma API do objeto app do Widget Svelte: fetchMatrix, columnFromString, addFilter, formatValue, etc.).config — um objeto com um valor por campo do Contrato, indexado pela chave de cada campo.Exemplo completo. Suponha um Contrato com três campos: titulo (Texto), corPrimaria (Cor) e colunaValor (Coluna):
<script>
export let app; // injeção automática do Horus
export let config; // valores preenchidos por quem configura o widget
let total = "…";
async function carregar() {
// config.colunaValor chega como string de coluna; converta antes de usar
const coluna = app.columnFromString(config.colunaValor);
const dados = await app.fetchMatrix({ columns: [coluna] });
// formatValue aplica o formato do sistema (moeda, decimais, locale)
total = app.formatValue(dados.rows?.[0]?.[0], coluna);
}
carregar();
</script>
<div class="p-4">
<h3 style="color: {config.corPrimaria}">{config.titulo}</h3>
<span class="text-3xl font-bold">{total}</span>
</div>NOTE
O config chega sempre completo: cada campo declarado no Contrato tem um valor — o que o usuário preencheu, o valor padrão do Contrato, ou um padrão seguro por tipo. O código nunca lê undefined num campo declarado.
O Contrato é um JSON com um array fields e, opcionalmente, um objeto display (a aparência fixa):
{
"fields": [
{ "key": "titulo", "type": "text", "label": "Título", "default": "Meu cartão" },
{ "key": "corPrimaria", "type": "color", "label": "Cor principal", "group": "Aparência" },
{ "key": "colunaValor", "type": "column-binding", "label": "Coluna de valor", "filter": "Measure" },
{ "key": "meta", "type": "number", "label": "Meta", "min": 0, "step": 100, "expression": true },
{ "key": "modo", "type": "select", "label": "Modo", "options": [
{ "value": "compacto", "label": "Compacto" },
{ "value": "detalhado", "label": "Detalhado" }
]}
],
"display": { "transparentBackground": false, "autoGrow": false }
}Propriedades comuns a todo campo: key (obrigatória e única), type (obrigatória), label (obrigatória), default, help (texto de ajuda), group (agrupamento visual).
type | Na interface | Para quê | Propriedades específicas |
|---|---|---|---|
column-binding | Coluna | O usuário escolhe uma coluna de dados. O valor chega como string de coluna (use app.columnFromString). | multiple (permite várias; o valor vira array), filter ("Measure", "Dimension", "Date" ou "All") |
text | Texto | Título, legenda, rótulo curto. | — |
textarea | Área de Texto | Textos longos, descrições. | — |
number | Número | Valor numérico. | min, max, step |
range | Intervalo | Valor numérico escolhido num controle deslizante. | min, max, step |
color | Cor | Seletor de cor (o valor chega como hex, ex.: #4F46E5). | — |
boolean | Booleano | Liga/desliga uma opção. | — |
select | Seleção | Escolha entre opções pré-definidas pelo autor. | options (array de { value, label }), forceKind ("segmented" para pílulas ou "list" para dropdown; sem ele a aparência é automática pelo número de opções) |
date | Data | Seleção de data. | — |
icon | Ícone | Seletor de ícone (o valor chega como nome iconify, ex.: fa:star). | — |
number-format | Formato numérico | O usuário escolhe um formato de número do sistema; combine com app.formatValue. | — |
svelte_modal | Editor Svelte (modal) | Abre uma tela de configuração personalizada, feita pelo próprio autor num dos arquivos do componente, para opções complexas. | editorComponent (arquivo .svelte do editor), buttonLabel (texto do botão que abre o modal) |
Quando o usuário não preenche um campo, o componente recebe o default declarado no Contrato. Sem default, entra um padrão seguro por tipo: 0 (ou o min) para número e intervalo, false para booleano, #000000 para cor, a primeira opção para seleção, [] ou "" para coluna (conforme multiple), {} para editor modal e "" para os demais.
expression) Campos de cor, número, texto, área de texto, intervalo e formato numérico aceitam "expression": true. Com isso, quem configura pode alternar o campo para o modo fórmula e escrever uma expressão JavaScript avaliada em tempo de render (útil para cor condicional, metas dinâmicas, etc.). Se a expressão falhar, vale o valor fixo do campo.
Enquanto o editor do componente está aberto, o widget de onde você o abriu reflete as mudanças de código e de Contrato na hora, sem salvar nada. Esse widget mostra o selo "Prévia da edição".
NOTE
A prévia vale apenas para o widget que está sendo editado. As outras instâncias do mesmo componente (no mesmo dashboard ou em outros) continuam mostrando a versão do canal delas. Ao fechar o editor, a prévia termina e o widget volta a mostrar o que está salvo.
Para testar um rascunho salvo num widget específico, use o canal da instância (abaixo).
Cada instância do componente aponta para um canal, visível no configurador do widget (apenas para quem pode editar o componente):
No modo de edição do dashboard, instâncias em rascunho exibem o selo "Rascunho".
WARNING
Publicar retorna todas as instâncias ao canal Publicado. O canal Rascunho de uma instância é um estado temporário de teste, e o rascunho de um componente é um só — instâncias em rascunho, em qualquer dashboard, mostram esse mesmo rascunho.
Um componente tem dois canais permanentes, Rascunho e Publicado, e três ações sobre eles:
| Ação | O que faz | O que acontece com o rascunho |
|---|---|---|
| Publicar | Copia o rascunho para o canal Publicado, em todas as dashboards onde o componente está instalado. | Continua igual ao publicado (sem pendências). |
| Desfazer publicação | O canal Publicado volta à versão publicada anterior (um nível de desfazer), em todas as dashboards. | Não muda. Suas edições continuam no rascunho. |
| Descartar rascunho | O rascunho volta a ser uma cópia do publicado. Use quando quiser abandonar as mudanças em andamento. | É sobrescrito pelo conteúdo publicado. |
WARNING
Mudanças de código ou de Contrato só chegam a quem usa depois de Publicar. Antes disso, elas existem apenas no rascunho.
O indicador "Afeta N dashboards" mostra onde o componente está instalado (espaço, aplicação, dashboard e canal) — útil para saber o impacto antes de publicar.
NOTE
Um componente recém-criado, ainda sem versão publicada, já renderiza o rascunho onde foi instanciado — justamente para você conseguir testá-lo. Ele só aparece na biblioteca para outras pessoas adicionarem depois de publicado.
Além das ações no editor do Dashboard, o console administrativo (HEC) tem a tela Biblioteca de Widgets (menu Recursos e Permissões), pensada para curadoria:
A aparência é a definida pelo autor. Você não edita o código nem escolhe o canal — apenas configura os valores.
| Ação | Quem pode |
|---|---|
| Criar, editar (código/Contrato/aparência), publicar, desfazer publicação, descartar rascunho; escolher canal da instância | Administradores (do cliente, ou do espaço quando não há cliente) e o suporte Horus |
| Adicionar o componente e configurar os campos | Qualquer usuário com permissão de editar dashboards |
Para quem só configura, as ações de edição e de canal nem aparecem — apenas os campos configuráveis.
Cada usuário vê na biblioteca os componentes do seu cliente mais os do seu espaço.
No painel de IA do editor é possível gerar o componente por linguagem natural: descreva o que quer e a IA produz o código e o Contrato (os campos configuráveis) já acoplados. Você revisa, ajusta e publica.