Configuration
This guide covers all configuration options available in Easy Email Pro. The configuration object is passed to Retro.useCreateConfig() or directly to EmailEditorProvider.
Configuration Overview​
The editor configuration is divided into several categories:
- Required Properties: Essential options that must be provided
- Handlers: Callback functions for user actions
- UI Features: Options to show/hide interface elements
- Content Configuration: Settings for blocks, fonts, merge tags, etc.
- Advanced Options: Advanced features and customizations
Required Properties​
| Property | Type | Description | Default |
|---|---|---|---|
clientId | string | Your Easy Email Pro client ID. Used for authentication and feature authorization. | Required |
initialValues | EmailTemplate | The initial email template data. This defines the starting state of the editor. | Required |
height | string | Editor container height. Use CSS values like "100vh", "calc(100vh - 66px)", etc. | Required |
onSubmit | (values: EmailTemplate, editor: CustomSlateEditor) => void | Called when the user manually triggers save/submit. Use this to save templates to your backend. | Required |
Example:
const config = Retro.useCreateConfig({
clientId: process.env.CLIENT_ID!, // Your Easy Email Pro client ID
initialValues: {
subject: "Welcome Email",
content: {
/* page element */
},
},
height: "calc(100vh - 66px)",
onSubmit: async (values) => {
await saveTemplate(values);
},
enabledAutoComplete: true,
});
Event Handlers​
| Property | Type | Description | Default |
|---|---|---|---|
onUpload | (blob: Blob) => Promise<string> | Handles file uploads (images, etc.). Must return the uploaded file URL. | Optional |
onChange | (values: EmailTemplate, editor: CustomSlateEditor) => void | Called whenever the template is modified. Useful for auto-save, validation, or tracking changes. | Optional |
Example:
const onUpload = async (file: Blob): Promise<string> => {
const formData = new FormData();
formData.append("file", file);
const response = await fetch("/api/upload", {
method: "POST",
body: formData,
});
const { url } = await response.json();
return url;
};
const onChange = (values: EmailTemplate) => {
// Auto-save, validate, or track changes
console.log("Template changed:", values);
};
UI Features​
These options control which interface elements are visible in the editor.
| Property | Type | Description | Default |
|---|---|---|---|
showSidebar | boolean | Show the left sidebar with block categories | true |
showLayer | boolean | Show the layer tree panel in the sidebar | false |
layerDefaultCollapsed | boolean | Set the default collapsed state of the layer panel. When enabledAutoComplete is true and this is not set, it defaults to true (collapsed). | undefined |
showPreview | boolean | Show the email preview panel (desktop/mobile tabs) | false |
showSourceCode | boolean | Show the JSON source code panel | false |
showBlockPaths | boolean | Show breadcrumb path for the selected block ![]() | false |
showPreviousLevelIcon | boolean | Show icon to navigate to parent element ![]() | false |
showTextHTMLMode | boolean | Allow HTML editing mode in text blocks ![]() | false |
showLogic | boolean | Show loop/condition configuration panels | false |
controller | boolean | Show zoom in/out controller ![]() | false |
compact | boolean | Use single sidebar layout instead of double sidebar | false |
showDragMoveIcon | boolean | Show drag handle icons on blocks | true |
showInsertTips | boolean | Show insertion hints when dragging blocks | true |
showGenerateBlockImage | boolean | Show button to download block screenshots ![]() | false |
Recommended Configuration:
{
showSidebar: true,
showLayer: true,
showPreview: true,
showSourceCode: true,
compact: false,
enabledAutoComplete: true,
}
Content Configuration​
| Property | Type | Description | Default |
|---|---|---|---|
categories | Categories | Configure block categories and available elements in the sidebar. See Block Categories for details. | Default categories |
fontList | Array<{value: string; label: string; href?: string}> | Custom font list. Web fonts require href for @import or link tag. | Default fonts |
mergetags | MergetagItem[] | Merge tag structure for dynamic content. Defines available variables like {{user.name}}. | [] |
mergetagsData | Record<string, any> | Data object used to preview merge tags. Replaces {{variables}} with actual values. | {} |
Example - Merge Tags:
const mergetags = [
{
label: "User",
value: "",
children: [
{ label: "Name", value: "user.name" },
{ label: "Email", value: "user.email" },
],
},
];
const mergetagsData = {
user: {
name: "John Doe",
email: "john@example.com",
},
};
Example - Font List:
const fontList = [
{ value: "Arial", label: "Arial" },
{
value: "Roboto",
label: "Roboto",
href: "https://fonts.googleapis.com/css2?family=Roboto",
},
{ value: "Custom Font", label: "Custom", href: "/fonts/custom.css" },
];
Advanced Features​
| Property | Type | Description | Default |
|---|---|---|---|
clientId | string | Client ID for paid plans. Required for premium features. | undefined |
instanceRef | React.MutableRefObject<EditorContextProps> | Reference to access editor instance programmatically. Useful for custom integrations. | undefined |
localeData | Record<string, string> | Translation data for localization. See Localization API. | {} |
sourceCodeEditable | boolean | Allow direct editing of JSON source code | false |
emptyPageElement | PageElement | Default element shown when canvas is cleared | Default empty page |
quantityLimitCheck | (params: { element: Element; pageData: PageElement }) => boolean | Validation callback when adding blocks. Return false to prevent addition. | undefined |
universalElementSetting | Object | Configuration for universal (reusable) blocks. See Universal Blocks. | undefined |
AIAssistant | Object | AI assistant configuration. See AI Assistant. ![]() | undefined |
unsplash | {clientId: string; presetList?: Array} | Unsplash integration for image library. Requires Unsplash API client ID. ![]() | undefined |
Feature Flags​
These options enable/disable specific editor features:
| Property | Type | Description | Default |
|---|---|---|---|
enabledAutoComplete | boolean | Enable automatic container structure completion. When enabled, content elements can be placed directly under PAGE or WRAPPER, and the system will automatically wrap them with SECTION and COLUMN containers during rendering. Also sets layer panel to collapsed by default. | false |
enabledGradientImage | boolean | Enable gradient background image generation for supported blocks ![]() | false |
enabledButtonIcon | boolean | Enable icon configuration for buttons (left/right icons) ![]() | false |
enabledAutoComplete​
The enabledAutoComplete feature automatically completes the necessary container structure (SECTION and COLUMN) when rendering content elements. This simplifies the template structure by allowing content elements to be placed directly under PAGE or WRAPPER elements.
How it works:
Automatic Wrapping: When a content element (like text, image, button, etc.) is placed directly under PAGE or WRAPPER, the system automatically wraps it with SECTION and COLUMN containers during rendering.
Layer Panel: When enabled, the layer panel defaults to collapsed state (if
layerDefaultCollapsedis not explicitly set).Parent Category Validation: Allows content elements to be valid children of PAGE or WRAPPER elements when auto-complete is enabled.
Use Cases:
- Simplify template structure by reducing manual container creation
- Allow content elements to be placed directly at the page level
- Automatically ensure proper email structure during rendering
Example:
const config = Retro.useCreateConfig({
// ... other config
enabledAutoComplete: true,
});
When enabledAutoComplete is true, you can place content elements directly under PAGE:
// Without autoComplete: Must manually add SECTION and COLUMN
{
type: "page",
children: [
{
type: "section",
children: [
{
type: "column",
children: [
{ type: "standard-text", /* ... */ }
]
}
]
}
]
}
// With autoComplete: Can place content directly
{
type: "page",
children: [
{ type: "standard-text", /* ... */ } // Automatically wrapped during render
]
}
The system will automatically add the SECTION and COLUMN wrappers during rendering, ensuring the email structure is valid.
layerDefaultCollapsed​
The layerDefaultCollapsed option controls the initial collapsed state of the layer panel (block tree view) in the sidebar.
Behavior:
- When set to
true: The layer panel starts with all blocks collapsed - When set to
false: The layer panel starts with all blocks expanded - When
undefined: The default behavior depends onenabledAutoComplete:- If
enabledAutoCompleteistrue, defaults totrue(collapsed) - Otherwise, defaults to
false(expanded)
- If
Use Cases:
- Improve performance when working with large templates by starting collapsed
- Provide a cleaner initial view for complex email structures
- Work in conjunction with
enabledAutoCompleteto provide a simplified initial state
Example:
const config = Retro.useCreateConfig({
// ... other config
showLayer: true,
layerDefaultCollapsed: true, // Start with all blocks collapsed
});
Note: Users can still manually expand/collapse individual blocks or use the "Collapse All" toggle in the layer panel, regardless of this initial setting.
Block Categories​
The categories property defines which blocks appear in the sidebar and how they're organized.
Example:
const categories: Categories = [
{
label: "Content",
active: true,
displayType: "grid",
blocks: [
{
type: ElementType.STANDARD_TEXT,
icon: <IconFont iconName="icon-text" />,
},
{
type: ElementType.STANDARD_IMAGE,
icon: <IconFont iconName="icon-img" />,
},
],
},
{
label: "Layout",
active: true,
displayType: "column",
blocks: [
{
title: "2 Columns",
payload: [
["50%", "50%"],
["33%", "67%"],
],
},
],
},
];
For more details on configuring categories, see the Examples Section.
Complete Configuration Example​
Here's a complete example showing all configuration options:
import { Retro } from "easy-email-pro-theme";
import { ElementType } from "easy-email-pro-core";
const config = Retro.useCreateConfig({
// Required
initialValues: templateData,
height: "calc(100vh - 66px)",
onSubmit: async (values) => {
await saveTemplate(values);
},
// Handlers
onUpload: async (file) => {
return await uploadToServer(file);
},
onChange: (values) => {
// Handle changes
},
// UI Features
showSidebar: true,
showLayer: true,
showPreview: true,
showSourceCode: true,
showBlockPaths: true,
compact: false,
// Feature Flags
enabledAutoComplete: true,
// Content
categories: [
{
label: "Content",
active: true,
displayType: "grid",
blocks: [
{
type: ElementType.STANDARD_TEXT,
icon: <IconFont iconName="icon-text" />,
},
{
type: ElementType.STANDARD_IMAGE,
icon: <IconFont iconName="icon-img" />,
},
],
},
],
mergetags: [
{
label: "User",
value: "",
children: [{ label: "Name", value: "user.name" }],
},
],
mergetagsData: {
user: { name: "John" },
},
// Advanced
clientId: process.env.CLIENT_ID,
localeData: translationData,
});
Type Definitions​
For complete TypeScript type definitions, refer to the EmailEditorProps interface. All configuration options are fully typed for better development experience.
export interface EmailEditorProps {
// Required properties
initialValues: EmailTemplate;
height: string;
onSubmit: (values: EmailTemplate) => void;
// Optional handlers
onUpload?: (blob: Blob) => Promise<string>;
onChange?: (values: EmailTemplate, editor: CustomSlateEditor) => void;
// ... (see full interface in source code)
}
For the complete interface definition with all properties, check the TypeScript definitions in the easy-email-pro-editor package.
Additional Type Definitions​
Here are some commonly used type definitions for reference:
export interface MergetagItem {
label: string;
value: string;
children?: MergetagItem[];
selectable?: boolean;
type?: "text" | "image" | "link";
}
export interface CategoryGridItem<T extends keyof ElementMap = any> {
label: string;
active?: boolean;
blocks: Array<{
type: Element["type"];
payload?: Partial<ElementMap[T]>;
title?: string | undefined;
icon?: React.ReactNode;
}>;
displayType?: "grid";
}
export type Categories = Array<
| CategoryGridItem
| {
label: string;
active?: boolean;
blocks: Array<{
payload: string[][];
title: string | undefined;
}>;
displayType: "column";
}
| {
label: string;
active?: boolean;
blocks: Array<{
payload?: Partial<Element>;
}>;
displayType: "widget";
}
| {
label: string;
active?: boolean;
blocks: Array<React.ReactNode>;
displayType: "custom";
}
>;








