Documentação Guias
Blocos personalizados
Defina blocos de e-mail com campos na sua aplicação e renderize pelo SDK de integração.
Nesta página
Definir um bloco
Informe customBlocks como array. As funções de renderização executam na sua aplicação, de forma síncrona ou por promise. O iframe recebe definições JSON e um fragmento HTML de corpo. O SDK não depende do runtime React.
<script src="https://weavour.com/editor/sdk/0.1.12/editor.js"></script>
<div id="email-editor" style="height: 800px"></div>
<script>
const escapeHTML = value => String(value).replace(/[&<>"']/g, char =>
({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[char]));
const editor = Weavour.mount('#email-editor', {
editorKey: 'YOUR_PUBLIC_EDITOR_KEY',
userId: 'user-123', organizationId: 'org-456',
customBlocks: [{
id: 'product-card', version: 1, label: 'Product card',
defaultProps: { title: 'New product', href: 'https://example.com/product' },
controls: {
title: { type: 'text', label: 'Product name', required: true },
href: { type: 'url', label: 'Product link' },
},
render: props => '<table role="presentation" width="100%"><tbody><tr>' +
'<td style="padding:24px"><h2>' + escapeHTML(props.title) + '</h2>' +
'<a href="' + escapeHTML(props.href) + '">View product</a></td></tr></tbody></table>',
}],
onDocumentChange(document) { /* Save the complete envelope in your backend. */ },
});
</script>Referência da definição
| Propriedade | Contrato |
|---|---|
| id | ID estável: começa com letra, depois letras, números, sublinhados ou hífens; até 64 caracteres. |
| version | Inteiro positivo. Com id, identifica exatamente a função de renderização e os controles. |
| label | Nome de exibição definido pelo cliente, até 200 caracteres. O editor não traduz nomes do cliente. |
| defaultProps | Objeto JSON copiado para novos blocos; propriedades salvas existentes não mudam. |
| controls | Definições de campos por nome de propriedade, com rótulo e valor padrão compatível. |
| render(props) | Retorna um fragmento HTML de corpo com estilos inline ou Promise<string>; executa na sua aplicação. |
| iconSvg | String SVG estática opcional que substitui o esquema automático da paleta. |
Usar React Email
Instale React, @react-email/components e @react-email/render na sua aplicação. Testado com components 1.0.12, render 2.2.0 e React 19.3.1: Section, Row, Column, Text, Button e Img. Retorne um fragmento de corpo independente; omita Html, Head, Body e estilos do head.
import { defineCustomBlock } from '@weavour/editor';
import { WeavourEditor } from '@weavour/react';
import { Section, Text, Button } from '@react-email/components';
import { render } from '@react-email/render';
export const productCard = defineCustomBlock({
id: 'product-card', version: 1, label: 'Product card',
defaultProps: { title: 'New product', href: 'https://example.com/product' },
controls: {
title: { type: 'text', label: 'Product name', required: true },
href: { type: 'url', label: 'Product link' },
},
async render(props) {
const html = await render(
<Section><Text>{props.title}</Text>
<Button href={props.href} style={{ padding: '12px 24px' }}>View product</Button>
</Section>
);
// React Email adds a doctype even when rendering a body fragment.
return html.replace(/^<!doctype[^>]*>/i, '');
},
});
export function CampaignEditor() {
return <WeavourEditor
editorKey="YOUR_PUBLIC_EDITOR_KEY"
userId="user-123" organizationId="org-456"
customBlocks={[productCard]} style={{ height: 800 }}
/>;
}Controles e propriedades de imagens
Todo controle precisa de rótulo e propriedade padrão compatível. Controles de imagem abrem a biblioteca do escopo e o recorte. O descritor é { src, assetId, width, height, alt }; renderize usando src e alt. IDs de arquivos nunca concedem acesso. Outras propriedades JSON limitadas podem guardar dados salvos do cliente.
| Tipo | Valor | Opções |
|---|---|---|
| text / textarea | string | placeholder, required, maxLength |
| url | string | required; merge tags |
| image | descriptor | null | required; src, assetId, width, height, alt |
| number | number | min, max, step |
| select | string | options: [{ label, value }] |
| boolean | boolean | |
| color | string | #rrggbb |
Inserir e editar
Blocos personalizados aparecem após os padrão na mesma grade, sem título nem separador. Os blocos da organização vêm depois. A busca acima da grade filtra os três tipos por nome; limpe o campo ou pressione Escape para restaurar a paleta. Clique, arraste ou foque um bloco e pressione Enter para inserir. O painel gera controles a partir da definição; campos de seleção usam o mesmo menu com tema dos controles padrão. Mover, duplicar, excluir e desfazer funcionam normalmente. Durante a renderização, novos blocos reservam uma área vazia; atualizações mantêm a última prévia e mostram um indicador na lateral. Erros e novas tentativas ficam na lateral, fora do conteúdo do e-mail.
Ícones da paleta
Sem iconSvg, a paleta desenha um esquema a partir do layout de render(defaultProps) no navegador. Reutiliza uma captura salva compatível; caso contrário, executa a função uma vez por definição e geração do registro, dentro dos limites compartilhados. Os ícones são mantidos entre abas e temas. A medição não carrega recursos externos; imagens sem dimensões usam espaços reservados. Uma falha mantém um ícone genérico para inserção. Defina iconSvg com uma string SVG estática e viewBox para substituir o esquema e evitar a renderização da paleta. Geometria aceita: g, path, rect, circle, ellipse, line, polyline e polygon. Cores seguem o tema e preservam none. Scripts, eventos, estilos, texto, referências e conteúdo incorporado são rejeitados. Limites: 16 KiB UTF-8, 128 elementos, 12 níveis. Ícones não alteram documentos, histórico nem exportações.
// Optional property on a custom-block definition. Omit for an automatic outline.
const iconSvg = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">' +
'<rect x="3" y="3" width="18" height="18" rx="2"/>' +
'<path d="M7 8h10M7 12h6M7 16h8"/></svg>';
// Keep the renderer and controls; replace only the palette icon.
editor.updateConfig({ customBlocks: [{ ...productCard, iconSvg }] });Versões e configuração em tempo real
Registre pares exatos (id, version); a paleta insere a maior versão registrada. Aumente version quando mudar comportamento, padrões ou semântica dos controles. Mantenha versões antigas para editar conteúdo antigo. Definições alteradas nunca reescrevem propriedades nem capturas existentes. customBlocks no nível superior prevalece sobre editorConfig.customBlocks; updateConfig({ customBlocks }) substitui o registro, [] limpa e omissão preserva. A propriedade React atualiza sem remontar.
// productCard is the definition from the React Email example above.
editor.updateConfig({ customBlocks: [productCard] });
// Include each custom ID when supplying an explicit insertion allowlist.
editor.updateConfig({
allowedBlocks: ['text', 'heading', 'section', 'custom:product-card'],
});
// Remove registrations without deleting existing email content.
editor.updateConfig({ customBlocks: [] });Salvamento, prévias e exportação
Salve o envelope completo do esquema 3 em onDocumentChange e reabra com emailDocument. Ele contém referência, propriedades e captura HTML validada de cada bloco; callbacks e metadados de ícones não são salvos. Rascunhos preservam edições não resolvidas. Exportação, teste, criação de modelo e salvamento de blocos da organização aguardam o resultado atual e falham se indisponível. Uma função de renderização ausente preserva capturas válidas para prévia e exportação e desativa a edição dos campos. Reabrir uma captura válida não renderiza novamente esse nó; a paleta pode renderizar os padrões para criar seu ícone. Prévias no painel usam capturas. Blocos da organização são layouts reutilizáveis com blocos nativos ou personalizados; salvar exige organizationId.
Política de HTML e personalização
Retorne tabelas, links, textos e imagens de e-mail com estilos inline. Comentários de botões compatíveis com Outlook são preservados. Scripts, eventos, formulários, frames, objetos, elementos de documento, CSS de head, classes que exigem estilos globais e URLs em CSS são rejeitados com erro. Escape valores escritos. Tokens conhecidos permanecem literais nos callbacks; use variáveis configuradas e layouts condicionais para personalização por destinatário. A Weavour não busca dados de destinatários.
Restrições de blocos
Uma lista explícita allowedBlocks deve incluir custom:product-card para permitir inserir este exemplo. Sem lista, IDs personalizados registrados ficam disponíveis. Restrições preservam nós existentes. O transporte de código personalizado está desativado na demonstração pública. Atualize SDK e leitores hospedados antes de habilitar escrita do esquema 3; versões antigas falham explicitamente.
Limites e solução de problemas
Por montagem: 50 versões de definições, 32 controles por versão, 100 nós personalizados, 32 KiB UTF-8 de propriedades por nó, 100 KiB de HTML de captura, quatro renderizações ativas e 100 solicitações pendentes. A digitação espera 150 ms; a renderização expira em cinco segundos. Documentos do esquema 3 têm limite conjunto de 1.000.000 bytes, incluindo capturas e metadados; limites de transporte e API também valem. Funções devem terminar rápido e evitar efeitos colaterais; JavaScript síncrono não pode ser interrompido à força. Salve dados resolvidos nas propriedades para reproduzir o conteúdo. Tente novamente, restaure o registro exato ou reduza o HTML. A substituição completa por IA não está disponível em documentos com blocos personalizados.