DocumentaciónSDK en GitHub

Documentación Guías

Bloques personalizados

Define los campos y el renderizado de tus propios bloques en tu aplicación.

En esta página

Definir un bloque

Pasa un array customBlocks. Las funciones se ejecutan en tu aplicación y devuelven HTML o una promesa. El iframe recibe JSON y un fragmento HTML. El SDK no depende del entorno de React.

html
<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 =>
  ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[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>

Referencia de una definición

PropiedadContrato
idIdentificador estable: empieza con una letra, seguida de letras, números, guiones o guiones bajos; máximo 64 caracteres.
versionEntero positivo. Junto con id identifica el renderizado y los controles exactos.
labelNombre visible, hasta 200 caracteres. El editor no traduce las etiquetas de tu aplicación.
defaultPropsObjeto JSON que se copia al insertar; las propiedades guardadas no cambian.
controlsCampos por nombre de propiedad, cada uno con etiqueta y valor inicial compatible.
render(props)Devuelve un fragmento HTML con estilos en línea o Promise<string>; se ejecuta en tu aplicación.
iconSvgCadena SVG estática opcional que sustituye el esquema automático de la paleta.

Usar React Email

Instala React, @react-email/components y @react-email/render en tu aplicación. Probado con components 1.0.12, render 2.2.0 y React 19.3.1: Section, Row, Column, Text, Button e Img. Devuelve un fragmento autónomo; omite Html, Head, Body y estilos de cabecera.

tsx
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 imágenes

Cada control necesita una etiqueta y un valor inicial compatible. Las imágenes se eligen en la biblioteca del ámbito actual, con recorte. El descriptor es { src, assetId, width, height, alt }; renderiza con src y alt. Un assetId no concede acceso. Otras propiedades JSON limitadas pueden guardar datos de tu aplicación.

TipoValorOpciones
text / textareastringplaceholder, required, maxLength
urlstringrequired; merge tags
imagedescriptor | nullrequired; src, assetId, width, height, alt
numbernumbermin, max, step
selectstringoptions: [{ label, value }]
booleanboolean
colorstring#rrggbb

Insertar y editar

Los bloques personalizados aparecen después de los estándar en la misma cuadrícula Bloques, sin título ni separador. Los bloques de organización guardados aparecen al final de la misma cuadrícula. Buscar bloques filtra los tres tipos por nombre; borra el campo o pulsa Escape para verlos todos. Haz clic, arrastra una tarjeta o enfócala y pulsa Intro para insertar. El panel Bloque genera los campos de la definición; las listas usan el mismo menú y tema que los controles estándar. Puedes mover, duplicar, eliminar y deshacer. Durante el renderizado, un bloque nuevo reserva una zona vacía para seleccionarlo; las actualizaciones conservan la vista anterior y muestran un indicador en el panel lateral. Los errores y la opción de reintentar quedan en ese panel, fuera del contenido del correo.

Iconos de la paleta

Sin iconSvg, la paleta dibuja un esquema a partir de la disposición de render(defaultProps) en el navegador. Se reutiliza una captura guardada que coincida; si no existe, se llama a la función una vez por definición y generación del registro, con los límites de renderizado compartidos. Los iconos se conservan al cambiar de pestaña o tema. La medición no carga recursos externos; las imágenes sin dimensiones usan un marco orientativo. Si falla, un icono genérico mantiene disponible la inserción. Para sustituir el esquema y evitar esa llamada, pasa iconSvg: una cadena SVG estática con viewBox. Geometría admitida: g, path, rect, circle, ellipse, line, polyline y polygon. Los colores siguen el tema y conservan none. Se rechazan scripts, eventos, estilos, texto, referencias y contenido incrustado. Límites: 16 KiB UTF-8, 128 elementos, 12 niveles. Los iconos no modifican documentos, historial ni exportaciones.

typescript
// 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 }] });

Versiones y configuración dinámica

Registra pares exactos (id, version). La paleta inserta la versión más alta. Incrementa la versión al cambiar el renderizado, los valores iniciales o los controles. Conserva versiones anteriores para editar contenido antiguo. Las propiedades y las capturas existentes no cambian. customBlocks de primer nivel tiene prioridad sobre editorConfig.customBlocks. updateConfig({ customBlocks }) sustituye el registro, [] lo vacía y omitirlo lo conserva. Las propiedades React cambian sin volver a montar el editor.

typescript
// 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: [] });

Guardado, vistas previas y exportación

Guarda el objeto completo onDocumentChange de esquema 3 y ábrelo con emailDocument. Contiene referencias, propiedades y capturas HTML validadas; no guarda funciones ni iconos. Los borradores conservan cambios pendientes. Exportar, enviar pruebas y guardar plantillas o bloques de organización esperan el resultado actual. Sin la función correspondiente, las capturas válidas se conservan y los campos quedan deshabilitados. Abrir una captura válida no vuelve a renderizar ese bloque; la paleta puede evaluar los valores iniciales por separado para crear su icono. El panel usa las capturas guardadas. Los bloques de organización son diseños reutilizables con bloques estándar o personalizados; guardarlos requiere organizationId.

HTML y personalización

Devuelve tablas, enlaces, texto e imágenes con estilos en línea. Se conservan los comentarios Outlook compatibles. Se rechazan scripts, eventos, formularios, iframes, objetos, elementos de documento, CSS de cabecera y URL CSS. Escapa los valores. Las variables conocidas permanecen literales en las funciones; utiliza variables y condiciones de diseño para personalizar destinatarios. Weavour no obtiene sus datos.

Restricciones de bloques

Una lista allowedBlocks explícita debe incluir custom:product-card para insertar el ejemplo. Sin lista, los bloques registrados están disponibles. Las restricciones conservan los nodos existentes. El código personalizado está deshabilitado en la demo pública. Actualiza el SDK y los lectores alojados antes de habilitar la escritura de esquema 3; los clientes antiguos rechazan el contenido explícitamente.

Límites y solución de problemas

Por montaje: 50 versiones, 32 controles por versión, 100 bloques, 32 KiB de propiedades UTF-8 y 100 KiB de HTML por bloque, cuatro renderizados activos y 100 solicitudes pendientes. Pausa de escritura: 150 ms; tiempo máximo: cinco segundos. Los documentos de esquema 3 tienen un límite conjunto de 1 000 000 bytes, incluidas las vistas previas; también se aplican los límites de transporte. Las funciones deben terminar pronto y evitar efectos secundarios. JavaScript síncrono no puede interrumpirse. Guarda los datos resueltos en propiedades. Reintenta, registra la versión exacta o reduce el HTML. La IA de sustitución completa no está disponible con estos bloques.

¿Necesitas ayuda? Escríbenos