Skip to content
This plugin is new and currently in beta. For the stable version, please use the previous version of the plugin.

Stripo Extensions SDK Release Notes

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:

  • StructureVisibilityBuiltInControl
  • ContainerVisibilityBuiltInControl
  • ImageVisibilityBuiltInControl
  • ButtonVisibilityBuiltInControl
  • TextVisibilityBuiltInControl

New typography and styling controls for button blocks:

  • ButtonFontFamilyBuiltInControl - Font family selection for buttons
  • ButtonTextSizeBuiltInControl - Button text size control
  • ButtonTextStyleAndFontColorBuiltInControl - Combined text style and color control

New background and border controls:

  • ContainerBackgroundImageBuiltInControl - Set background images on containers
  • ContainerBorderBuiltInControl - Container border styling
  • StructureBackgroundImageBuiltInControl - 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
  • Block
  • Control
  • UIElement
  • ContextAction
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:

  1. If your class defines a constructor(), ensure you call super() inside it
  2. Ensure all required methods are implemented (validation will catch missing methods at runtime)
  3. 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:

  1. Change method signature to accept modifier: HtmlNodeModifier
  2. Use the provided modifier parameter directly
  3. Remove return statement
  4. 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:

  1. Rename getIconClass() to getIcon()

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
FontFamilyBuiltInControlTextFontFamilyBuiltInControlRenamed for clarity
LinkColorBuiltInControlTextLinkColorBuiltInControlRenamed for clarity
ButtonFontColorBuiltInControlButtonTextStyleAndFontColorBuiltInControlEnhanced functionality
BackgroundImageBuiltInControlUse ContainerBackgroundImageBuiltInControl or StructureBackgroundImageBuiltInControlRemoved - 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.