Appearance
Stripo Extensions SDK Change Log
v3.2.0
Overview
Version 3.2.0 is a minor release of the Stripo Extensions SDK that introduces support for a custom image library tab and enhanced image metadata capabilities. This release maintains full backward compatibility with v3.1.0.
Release Date: 09 November 2025
Release Type: Minor Release
Version: 3.2.0
Previous Version: 3.1.0
Editor Compatibility
The npm package version 3.2.0 is fully compatible with the Stripo Editor starting from version 2.43.0 and higher.
What's New
New: ExternalImageLibraryTab Class
A new class has been introduced to enable developers to create a custom tab within the build-in Stripo image library. This allows you to organize images from different sources into a separate tab for better user experience.

typescript
import { ExternalImageLibraryTab, ExternalGalleryImageSelectCallback } from '@stripoinc/ui-editor-extensions';
class MyCustomImageTab extends ExternalImageLibraryTab {
/**
* Returns the translated name/label for the tab
*/
getName(): string {
return 'My Images';
}
/**
* Opens the custom tab and renders your image library UI
* @param container - DOM element where you should render your UI
* @param onImageSelectCallback - Callback to invoke when user selects an image
*/
openImageLibraryTab(
container: HTMLElement,
onImageSelectCallback: ExternalGalleryImageSelectCallback
): void {
// Render your custom image library UI in the container
container.innerHTML = `
<div class="my-image-gallery">
<!-- Your custom image gallery UI -->
</div>
`;
// When user selects an image, call the callback
// onImageSelectCallback(imageData);
}
}
// Register in ExtensionBuilder
const extension = new ExtensionBuilder()
.withExternalImageLibraryTab(MyCustomImageTab)
.build();Full Example Implementation: How to Integrate an External Image Library Tab
Enhanced: ExternalGalleryImage Interface
The ExternalGalleryImage interface now supports optional metadata labels for additional image information:

typescript
import { ExternalGalleryImage } from '@stripoinc/ui-editor-extensions';
// Old (v3.1.0)
const image: ExternalGalleryImage = {
originalName: 'product.png',
width: 800,
height: 600,
sizeBytes: 102400,
url: 'https://example.com/product.png',
altText: 'Product image'
};
// New (v3.2.0) - with optional labels
const image: ExternalGalleryImage = {
originalName: 'product.png',
width: 800,
height: 600,
sizeBytes: 102400,
url: 'https://example.com/product.png',
altText: 'Product image',
labels: { // NEW: Optional metadata
category: 'Products',
photographer: 'John Doe',
license: 'Commercial',
tags: 'red, clothing, winter'
}
};Migration Guide
From v3.1.0 to v3.2.0
No Breaking Changes - Version 3.2.0 is fully backward compatible with v3.1.0. All existing code will continue to work without modifications.
v3.1.0
Overview
Version 3.1.0 is a minor release of the Stripo Extensions SDK that introduces new UI elements for creating orderable/sortable lists, enhanced control lifecycle hooks, and additional node query capabilities. This release maintains full backward compatibility with v3.0.0.
Release Date: 03 November 2025
Release Type: Minor Release
Version: 3.1.0
Previous Version: 3.0.0
Editor Compatibility
The npm package version 3.1.0 is fully compatible with the Stripo Editor starting from version 2.42.0 and higher.
What's New
New: Orderable UI Element
A new UI element has been introduced to create orderable/sortable lists within your custom controls. These elements enable users to reorder items through drag-and-drop or positioning controls.
typescript
import { UIElementType } from '@stripoinc/ui-editor-extensions';
// Available orderable element types
UIElementType.ORDERABLE // 'UE-ORDERABLE' - Container for orderable items
UIElementType.ORDERABLE_ITEM // 'UE-ORDERABLE-ITEM' - Individual orderable item
UIElementType.ORDERABLE_ICON // 'UE-ORDERABLE-ICON' - Icon for ordering controlsNew: Control onDocumentChanged() Lifecycle Hook
Controls now have access to a new lifecycle hook that is called whenever any part of the document template changes.
typescript
import { Control, ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
class MyControl extends Control {
getId(): string { return 'my-control'; }
getTemplate(): string { return '<div>...</div>'; }
/**
* NEW in v3.1.0
* Called when any part of the document template has changed
* @param node - The immutable HTML node representing current node instance
*/
onDocumentChanged(node: ImmutableHtmlNode): void {
// React to document-wide changes
// This can be frequent; use cautiously for performance-sensitive operations
const customValue = node.getAttribute('data-custom');
if (customValue) {
// Update control state based on document changes
}
}
}Important Notes:
- This hook can be called frequently during editing
- Use cautiously for performance-sensitive operations
- Receives the current node instance as a parameter
- Useful for controls that need to react to global template changes
Difference from onTemplateNodeUpdated():
onTemplateNodeUpdated(): Called when the node associated with this control's context is updatedonDocumentChanged(): Called when any part of the document template changes
New: Node Module Identification
The BaseImmutableNode interface now includes a method to retrieve the closest module ID associated with a node.
typescript
import { ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
// In your block or control
const moduleId = node.getClosestModuleId();
console.log('Closest module ID:', moduleId);Use Cases:
- Identifying which module a node belongs to
- Module-specific operations and logic
Example Implementation:
The External Merge Tags Selector tutorial demonstrates practical usage of getClosestModuleId() for detecting module context and displaying contextual UI indicators.
Migration Guide
From v3.0.0 to v3.1.0
No Breaking Changes - Version 3.1.0 is fully backward compatible with v3.0.0. All existing code will continue to work without modifications.
v3.0.0
Overview
Version 3.0.0 is a major release of the Stripo Extensions SDK that introduces significant architectural improvements, enhanced TypeScript support, and new features for extending the Stripo email editor. This release includes breaking changes that require migration from v2.x.
Release Date: 20 October 2025
Release Type: Major Release
Version: 3.0.0
Previous Version: 2.0.2
Editor Compatibility
The npm package version 3.0.0 is fully compatible with the Stripo Editor starting from version 2.40.0 and higher.
What's New
Enhanced Package Distribution
The SDK now supports multiple module formats for better compatibility across different JavaScript environments:
- ESM (ECMAScript Modules): Modern ES module format
- CJS (CommonJS): Node.js compatible format
- Browser Bundle: Optimized browser-ready bundle
json
{
"exports": {
".": {
"types": "./dist/types/index.d.ts",
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.cjs",
"default": "./dist/esm/index.js"
},
"./browser": {
"browser": "./dist/browser/index.js",
"default": "./dist/browser/index.js"
}
}
}Migration: No code changes required. The package will automatically use the appropriate format for your environment.
New: Icons Registry
A new IconsRegistry class enables registration of custom SVG icons for use throughout your extensions.
typescript
import { IconsRegistry } from '@stripoinc/ui-editor-extensions';
class MyIconsRegistry extends IconsRegistry {
registerIconsSvg(iconsMap: Record<string, string>): void {
iconsMap['custom-icon'] = '<svg>...</svg>';
iconsMap['another-icon'] = '<svg>...</svg>';
}
}
// Register in ExtensionBuilder
const extension = new ExtensionBuilder()
.setIconsRegistry(MyIconsRegistry)
.build();Benefits:
- Centralized icon management
- SVG support for crisp, scalable icons
- Easy to share icons across multiple components
New: Control Visibility Management
Controls can now be dynamically shown or hidden based on the selected node's state.
typescript
import { Control } from '@stripoinc/ui-editor-extensions';
class MyControl extends Control {
// New method - implement to control visibility
isVisible(node: ImmutableHtmlNode): boolean {
// Show control only for specific block types
return node.hasClass('my-custom-block');
}
getId(): string { return 'my-control'; }
getTemplate(): string { return '<div>...</div>'; }
}Use Cases:
- Show controls only for specific block types
- Hide controls based on user permissions
- Conditional UI based on template state
New: Additional Built-in Controls Available
Pre-built visibility controls are now available for major block types:
StructureVisibilityBuiltInControlContainerVisibilityBuiltInControlImageVisibilityBuiltInControlButtonVisibilityBuiltInControlTextVisibilityBuiltInControl
New typography and styling controls for button blocks:
ButtonFontFamilyBuiltInControl- Font family selection for buttonsButtonTextSizeBuiltInControl- Button text size controlButtonTextStyleAndFontColorBuiltInControl- Combined text style and color control
New background and border controls:
ContainerBackgroundImageBuiltInControl- Set background images on containersContainerBorderBuiltInControl- Container border stylingStructureBackgroundImageBuiltInControl- Structure background images
New BlocksPanel Customization
Customize the modules tab icon in the blocks panel:
typescript
import { BlocksPanel } from '@stripoinc/ui-editor-extensions';
class MyBlocksPanel extends BlocksPanel {
getModulesTabIconName(modulesTab: {
key: string;
label: Record<string, string>
}): string | undefined {
return 'custom-modules-icon'; // Use registered icon
}
}Breaking Changes
1. Class Architecture: Abstract Classes Replaced with Validated Classes
BREAKING CHANGE: All extension base classes have been refactored from TypeScript abstract classes to regular classes with runtime validation.
Affected Classes
BlockControlUIElementContextAction
Old Implementation (v2.x)
typescript
import { Block } from '@stripoinc/ui-editor-extensions';
export class MyBlock extends Block {
// TypeScript enforced abstract method implementation
abstract getId(): string;
abstract getTemplate(): string;
abstract getIcon(): string;
abstract getName(): string;
abstract getDescription(): string;
}New Implementation (v3.0)
typescript
import { Block } from '@stripoinc/ui-editor-extensions';
export class MyBlock extends Block {
constructor() {
super(); // Now calls BaseValidatedClass constructor
}
// Methods now throw errors if not implemented
getId(): string { return 'my-block'; }
getTemplate(): string { return '<div>...</div>'; }
getIcon(): string { return 'icon.svg'; }
getName(): string { return 'My Block'; }
getDescription(): string { return 'Description'; }
}Why This Change?
- Improved runtime validation with clearer error messages
- Better developer experience with validation logging
Migration Steps:
- If your class defines a
constructor(), ensure you callsuper()inside it - Ensure all required methods are implemented (validation will catch missing methods at runtime)
- Test your extension - you'll see helpful error messages if methods are missing
2. Block Lifecycle Hooks: Signature Changes
BREAKING CHANGE: Several Block lifecycle hooks have changed their signatures.
onDocumentInit() - Return Type Removed
Old (v2.x):
typescript
onDocumentInit(): HtmlNodeModifier | undefined {
const modifier = this.api.getDocumentModifier();
// Make modifications
return modifier;
}New (v3.0):
typescript
onDocumentInit(): void {
const modifier = this.api.getDocumentModifier();
// Make modifications and apply them
modifier.apply(new ModificationDescription(`Some modifications applied`))
// No return value needed
}Migration: Remove the return statement and apply migrations with the appropriate description manually.
onSelect() - Return Type Removed
Old (v2.x):
typescript
onSelect(node: ImmutableHtmlNode): HtmlNodeModifier | undefined {
const modifier = this.api.getDocumentModifier();
// Make modifications
return modifier;
}New (v3.0):
typescript
onSelect(node: ImmutableHtmlNode): void {
const modifier = this.api.getDocumentModifier();
// Make modifications and apply them
modifier.apply(new ModificationDescription(`Some modifications applied`))
// No return value needed
}Migration: Remove the return statement and apply migrations with the appropriate description manually.
onCopy() - Parameters and Return Type Changed
Old (v2.x):
typescript
onCopy(
targetNode: ImmutableHtmlNode,
sourceNode: ImmutableHtmlNode
): HtmlNodeModifier | undefined {
const modifier = this.api.getDocumentModifier();
// Modify the copied node
return modifier;
}New (v3.0):
typescript
onCopy(modifier: HtmlNodeModifier): void {
// Use the provided modifier directly
// Modifier is already set up for the copy operation
modifier.setAttribute('data-copied', 'true');
// No return value
}Migration:
- Change method signature to accept
modifier: HtmlNodeModifier - Use the provided modifier parameter directly
- Remove return statement
- Your modifications will now be applied directly within the copy operation.
onDelete() - Return Type Removed
Old (v2.x):
typescript
onDelete(node: ImmutableHtmlNode): HtmlNodeModifier | undefined {
const modifier = this.api.getDocumentModifier();
// Make modifications
return modifier;
}New (v3.0):
typescript
onDelete(node: ImmutableHtmlNode): void {
const modifier = this.api.getDocumentModifier();
// Make modifications and apply them
modifier.apply(new ModificationDescription(`Some modifications applied`))
// No return value needed
}Migration: Remove the return statement and apply migrations with the appropriate description manually.
onDocumentChanged() - Now Receives Node Parameter
Old (v2.x):
typescript
onDocumentChanged(): void {
// React to any document changes
// No context about which node changed
}New (v3.0):
typescript
onDocumentChanged(node: ImmutableHtmlNode): void {
// React to document changes for this specific node
// The node parameter indicates which extension instance triggered the event
// For example, if you have multiple instances of a custom block (such as Coupon block), this hook will be called separately for each node, allowing you to distinguish between them (e.g., Coupon block 1 and Coupon block 2)
if (node.getAttribute('data-custom') === 'value') {
// Handle specific node changes
}
}Migration: Add the node: ImmutableHtmlNode parameter to your method signature.
3. Control Class: onTemplateNodeUpdated() Now Optional
BREAKING CHANGE: The onTemplateNodeUpdated() method is now optional with a default no-op implementation.
Old (v2.x):
typescript
import { Control } from '@stripoinc/ui-editor-extensions';
class MyControl extends Control {
abstract onTemplateNodeUpdated(node: ImmutableHtmlNode): void;
// HAD to implement this method
onTemplateNodeUpdated(node: ImmutableHtmlNode): void {
// Update UI based on node changes
}
}New (v3.0):
typescript
import { Control } from '@stripoinc/ui-editor-extensions';
class MyControl extends Control {
// Now optional - only implement if needed
onTemplateNodeUpdated(node: ImmutableHtmlNode): void {
// Update UI based on node changes
}
// Or omit entirely if you don't need it
}Migration: No changes required if you're already implementing this method. If you had empty implementations, you can remove them.
4. ContextAction: Method Renamed
BREAKING CHANGE: The getIconClass() method has been renamed to getIcon().
Old (v2.x):
typescript
import { ContextAction } from '@stripoinc/ui-editor-extensions';
class MyAction extends ContextAction {
getIconClass(): string {
return 'custom-icon';
}
}New (v3.0):
typescript
import { ContextAction } from '@stripoinc/ui-editor-extensions';
class MyAction extends ContextAction {
getIcon(): string {
return 'custom-icon'; // Icon name from IconsRegistry
}
}Migration:
- Rename
getIconClass()togetIcon()
5. Built-in Control Renames
BREAKING CHANGE: Several built-in controls have been renamed for clarity and consistency.
Font Family Controls
Old (v2.x):
typescript
import {
FontFamilyBuiltInControl, // Text font control
LinkColorBuiltInControl, // Text Link color
ButtonFontColorBuiltInControl, // Button font color
BackgroundImageBuiltInControl // Generic background
} from '@stripoinc/ui-editor-extensions';New (v3.0):
typescript
import {
TextFontFamilyBuiltInControl, // Renamed from FontFamilyBuiltInControl
TextLinkColorBuiltInControl, // Renamed from LinkColorBuiltInControl
ButtonFontFamilyBuiltInControl, // New - button specific
// BackgroundImageBuiltInControl - REMOVED, use specific controls below
ContainerBackgroundImageBuiltInControl, // Container specific
StructureBackgroundImageBuiltInControl // Structure specific
} from '@stripoinc/ui-editor-extensions';Migration Table:
| Old Name (v2.x) | New Name (v3.0) | Notes |
|---|---|---|
FontFamilyBuiltInControl | TextFontFamilyBuiltInControl | Renamed for clarity |
LinkColorBuiltInControl | TextLinkColorBuiltInControl | Renamed for clarity |
ButtonFontColorBuiltInControl | ButtonTextStyleAndFontColorBuiltInControl | Enhanced functionality |
BackgroundImageBuiltInControl | Use ContainerBackgroundImageBuiltInControl or StructureBackgroundImageBuiltInControl | Removed - use specific controls |
Extension Class Changes
New: iconsRegistry Support
The Extension class now supports icon registry configuration.
Old (v2.x):
typescript
const extension = new ExtensionBuilder()
.setI18n(translations)
.setStyles(styles)
.addBlock(MyBlock)
.build();New (v3.0):
typescript
const extension = new ExtensionBuilder()
.setI18n(translations)
.setStyles(styles)
.setIconsRegistry(MyIconsRegistry) // NEW
.addBlock(MyBlock)
.build();The Extension class now has:
getIconsRegistry(): ConstructorOfType<IconsRegistry> | undefined- NEW method
Migration: No changes required unless you want to use the new IconsRegistry feature.