Appearance
Block
Core class for creating custom blocks in the Stripo Email Editor Extensions SDK.
typescript
class Block
Description
The Block
class is the foundation for all custom blocks in the Stripo Email Editor. It provides the essential structure and lifecycle hooks for creating reusable email content components that integrate seamlessly with the editor's drag-and-drop interface, collaboration features, and template management system.
Blocks represent discrete pieces of email content, ranging from simple elements like buttons and images to complex structures containing other blocks. Each block type appears in the editor's blocks panel and can be dragged into email templates.
Import
typescript
import { Block } from '@stripoinc/ui-editor-extensions';
Properties
api
Provides access to editor functionalities specific to this block instance.
typescript
public api!: BlockApi
Type
Usage Notes
- Automatically injected by the editor when the block is instantiated
- Available in all lifecycle methods
- Provides access to template modification, translation, and editor state
Methods
getId()
Retrieves the unique identifier for this block type.
typescript
public getId(): string
Returns
string
- A unique identifier for the block type
Usage Notes
- Must be unique across all registered blocks
- Used for block registration and CSS class generation
Example
typescript
public getId(): string {
return 'my-custom-block';
}
getTemplate()
Retrieves the HTML template string that defines the initial structure of this block.
typescript
public getTemplate(): string
Returns
string
- HTML template for the block
Usage Notes
- Defines the initial HTML structure when the block is dragged into the editor
- Can use template aliases for common patterns
Example
typescript
public getTemplate(): string {
return `
<td>
<h2>Welcome!</h2>
<p>Your content here</p>
</td>
`;
}
getIcon()
Retrieves the URL or icon content representing this block in the editor's block panel.
typescript
public getIcon(): string
Returns
string
- Icon source (URL or data URI)
Usage Notes
- Displayed in the blocks panel
- Recommended size: 24x24px for optimal display
- Supports SVG, PNG, JPG formats
Example
typescript
import blockIcon from './assets/icon.svg';
public getIcon(): string {
return blockIcon;
}
getName()
Retrieves the display name of the block shown to users in the block panel.
typescript
public getName(): string
Returns
string
- Localized block name
Usage Notes
- Displayed in the blocks panel and tooltips
- Should be concise and descriptive
- Use
this.api.translate()
for localization support
Example
typescript
public getName(): string {
return this.api.translate('block.customBlock.name');
}
getDescription()
Retrieves a short description of the block shown to users, often as a tooltip in the block panel.
typescript
public getDescription(): string
Returns
string
- Localized description
Usage Notes
- Displayed as tooltip in blocks panel
- Should briefly explain the block's purpose
- Use
this.api.translate()
for localization
Example
typescript
public getDescription(): string {
return this.api.translate('block.customBlock.description');
}
isEnabled()
Determines if the block should be available for use in the editor.
typescript
public isEnabled(): boolean
Returns
boolean
- True if the block is enabled, false otherwise. Defaults to true
.
Usage Notes
- Override to provide conditional availability
- Can depend on editor configuration or user permissions
- Disabled blocks don't appear in the blocks panel
Example
typescript
public isEnabled(): boolean {
const config = this.api.getEditorConfig();
return config.features?.customBlocks === true;
}
canBeSavedAsModule()
Determines if the block can be saved as a reusable module by the user.
typescript
public canBeSavedAsModule(): boolean
Returns
boolean
- True if the block can be saved as a module. Defaults to false
.
Usage Notes
- Only applicable for STRUCTURE and CONTAINER composition types
- Enables "Save as Module" option in context menu
- Modules can be reused across different templates
Example
typescript
public canBeSavedAsModule(): boolean {
return this.getBlockCompositionType() === BlockCompositionType.STRUCTURE;
}
getContextActionsIds()
Specifies the context actions available for this block.
typescript
public getContextActionsIds(): string[] | undefined
Returns
string[] | undefined
- Array of context action IDs, or undefined to use defaults
Usage Notes
- Controls which actions appear in the block's context menu
- Use
ContextActionType
enum for standard actions - Can include custom action IDs registered via
ExtensionBuilder
- Return
undefined
to use default actions
Example
typescript
import { ContextActionType } from '@stripoinc/ui-editor-extensions';
public getContextActionsIds(): string[] {
return [
ContextActionType.COPY,
ContextActionType.MOVE,
'my-custom-action'
];
}
getCustomRenderer()
Provides a custom renderer class for this block, allowing for specialized rendering logic.
typescript
public getCustomRenderer(): ConstructorOfType<BlockRenderer> | undefined
Returns
ConstructorOfType<BlockRenderer> | undefined
- Constructor for a custom renderer class
Usage Notes
- Enables different display in editor vs. actual HTML
- Useful for showing merge tags as preview values
- Return
undefined
to use default rendering - Custom renderers disable inner block selection for STRUCTURE/CONTAINER types
Example
typescript
public getCustomRenderer(): ConstructorOfType<BlockRenderer> {
return MyCustomRenderer;
}
getUniqueBlockClassname()
Gets a unique CSS class name specifically for this block type.
typescript
public getUniqueBlockClassname(): string
Returns
string
- Unique CSS class name. Defaults to esd-{blockId}
.
Usage Notes
- Used for CSS targeting and block identification
- Applied to the block's root element
- Override only if custom class naming is required
Example
typescript
public getUniqueBlockClassname(): string {
return `custom-block-${this.getId()}`;
}
getBlockCompositionType()
Determines if block is atomic or composite.
typescript
public getBlockCompositionType(): BlockCompositionType
Returns
BlockCompositionType - The composition type. Defaults to BlockCompositionType.BLOCK
.
Usage Notes
BLOCK
- Atomic blockCONTAINER
- Can contain other atomic blocksSTRUCTURE
- Can contain containers with blocks
Example
typescript
public getBlockCompositionType(): BlockCompositionType {
return BlockCompositionType.STRUCTURE;
}
shouldDisplayQuickAddIcon()
Determines if block should be included in empty container quick insert actions list.
typescript
public shouldDisplayQuickAddIcon(): boolean
Returns
boolean
- True to show quick-add icon. Defaults to false
.
Usage Notes
- Adds block icon to quick-add menu in empty containers
- Provides faster access to frequently used blocks
Example
typescript
public shouldDisplayQuickAddIcon(): boolean {
return true;
}
allowInnerBlocksSelection()
Determines if nested blocks selection is allowed in extensions of type STRUCTURE or CONTAINER.
typescript
public allowInnerBlocksSelection(): boolean
Returns
boolean
- True to allow selection. Defaults to true
.
Usage Notes
- Only applicable for STRUCTURE and CONTAINER types
- When false, prevents users from selecting inner blocks
- Useful for blocks that should be edited as a whole unit
allowInnerBlocksDND()
Determines if nested blocks drag and drop is allowed in extensions of type STRUCTURE or CONTAINER.
typescript
public allowInnerBlocksDND(): boolean
Returns
boolean
- True to allow drag and drop. Defaults to true
.
Usage Notes
- Only applicable for STRUCTURE and CONTAINER types
- When false, prevents dragging blocks into or within the container
- Useful for fixed-layout blocks
Lifecycle Hooks
onDocumentInit()
Called when the editor document is initialized.
typescript
public onDocumentInit(): void
Usage Notes
- Executes once when document loads
- Useful for initial setup or validation
- Can modify existing block instances in the template
- Has access to the complete document via
this.api
Example
typescript
public onDocumentInit(): void {
// Ensure only one instance exists
const blocks = this.api.getDocumentRoot()
.querySelectorAll(`.${this.getUniqueBlockClassname()}`);
if (blocks.length > 1) {
// Remove extra instances
const modifier = this.api.getDocumentModifier();
for (let i = 1; i < blocks.length; i++) {
modifier.modifyHtml(blocks[i]).remove();
}
modifier.apply(new ModificationDescription('Removed duplicate blocks'));
}
}
onSelect()
Called when an instance of this block is selected in the editor.
typescript
public onSelect(node: ImmutableHtmlNode): void
Parameters
Parameter | Type | Description |
---|---|---|
node | ImmutableHtmlNode | The selected block instance |
Usage Notes
- Triggered each time user selects the block
- Can be used to update UI or gather analytics
- Has access to the specific block instance via
node
Example
typescript
public onSelect(node: ImmutableHtmlNode): void {
console.log('Block selected:', node.getAttribute('id'));
// Perform other actions
}
onCopy()
Called when an instance of this block is copied.
typescript
public onCopy(modifier: HtmlNodeModifier): void
Parameters
Parameter | Type | Description |
---|---|---|
modifier | HtmlNodeModifier | The HTML node modifier for the copied block instance |
Usage Notes
- Executes on block duplication
- Useful for resetting unique identifiers or state
- Use the
modifier
to make changes to the copied block - The modifier is already focused on the newly copied block node
Example
typescript
public onCopy(modifier: HtmlNodeModifier): void {
// Reset unique ID on copied block
modifier.setAttribute('data-id', generateUniqueId());
}
onDelete()
Called when an instance of this block is deleted.
typescript
public onDelete(node: ImmutableHtmlNode): void
Parameters
Parameter | Type | Description |
---|---|---|
node | ImmutableHtmlNode | The block instance being deleted |
Usage Notes
- Executes before block removal
- Useful for cleanup operations
- Can modify other parts of the document
Example
typescript
public onDelete(node: ImmutableHtmlNode): void {
// Clean up associated CSS rules
const blockId = node.getAttribute('data-id');
const cssRule = this.api.getDocumentRootCssNode()
.querySelector(`#${blockId}`);
if (cssRule) {
this.api.getDocumentModifier()
.modifyCss(cssRule).removeRule()
.apply(new ModificationDescription('Removed block styles'));
}
}
onCreated()
Called after a new instance of this block is created and added to the document.
typescript
public onCreated(node: ImmutableHtmlNode): void
Parameters
Parameter | Type | Description |
---|---|---|
node | ImmutableHtmlNode | The newly created block instance |
Usage Notes
- Triggered after drag-and-drop or programmatic insertion
- Useful for initialization or default configuration
Example
typescript
public onCreated(node: ImmutableHtmlNode): void {
// Set default configuration
const modifier = this.api.getDocumentModifier();
modifier.modifyHtml(node)
.setAttribute('data-created', new Date().toISOString())
.setNodeConfig({ initialized: true })
.apply(new ModificationDescription('Initialized new block'));
}
onDocumentChanged()
Called when any part of the document template has changed.
typescript
public onDocumentChanged(node: ImmutableHtmlNode): void
Parameters
Parameter | Type | Description |
---|---|---|
node | ImmutableHtmlNode | The current block instance |
Usage Notes
- Triggered frequently during editing
- Use cautiously for performance-sensitive operations
- Consider debouncing or throttling if needed
- Useful for maintaining document-wide consistency
- The
node
parameter provides access to the root template node
Example
typescript
private changeTimeout: number;
public onDocumentChanged(node: ImmutableHtmlNode): void {
// Debounce updates
clearTimeout(this.changeTimeout);
this.changeTimeout = setTimeout(() => {
// Access current node configuration
const config = node.getNodeConfig();
this.updateTemplateState(config);
}, 500);
}