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

Working with Components APIs

Core API System

The Stripo Extensions SDK provides a hierarchical API system where each extension component (Block, Control, UIElement, etc.) has access to specific API methods through the this.api property.

API Inheritance Hierarchy

javascript
BaseApi
├── BlockApi (extends BaseApi + BaseModifierApi)
├── ControlApi (extends BaseApi + BaseModifierApi)
├── UIElementApi (extends BaseApi)
├── ContextActionApi (extends BaseApi + BaseModifierApi)
├── BlockRendererApi (extends BaseApi)
├── SettingsPanelApi (extends BaseApi)
└── BlocksPanelApi (extends BaseApi)

Examples

General API Usage

Getting Editor Configuration

One of the most common tasks is configuring custom blocks based on the editor configuration. In this example, we will use the following editor configuration:

javascript
window.UIEditor.initEditor(
    document.querySelector('#stripoEditorContainer'),
    {
        html: template.html,
        css: template.css,
        metadata: {
            emailId: `email_1`,
            username: 'Demo User'
        },
        ...,
        extensions: [
            ...
        ],
        simpleBlockConfig: {
            enabled: true,
            item: 'IPhone 17'
        }
    }
);

//===========================================================

import {Block} from '@stripoinc/ui-editor-extensions';

export class SimpleBlock extends Block {
    isEnabled() {
        return this.api.getEditorConfig().simpleBlockConfig?.enabled || true;
    }

    getBlockCompositionType() {
        return BlockCompositionType.STRUCTURE;
    }

    getTemplate() {
        return `
            <${BlockType.STRUCTURE}>
                <${BlockType.CONTAINER}>
                    <${BlockType.BLOCK_TEXT}>
                        ${this.api.getEditorConfig().simpleBlockConfig?.item || 'Unknown'}
                    </${BlockType.BLOCK_TEXT}>
                </${BlockType.CONTAINER}>
            </${BlockType.STRUCTURE}>
        `
    }

    // Additional block configuration methods...
}

Translation and Internationalization

Use the translation API to support multiple languages:

javascript
// uk.js - Ukrainian translations
export default {
    "Buy": "Купити",
    "Set event-id {eventId}": "Встановлено event-id {eventId}"
}
//===============================================================
import uk from './uk';
import {Block, ModificationDescription} from '@stripoinc/ui-editor-extensions';

export class SimpleBlock extends Block {
    getTemplate() {
        return `
            <td>
                <a href="https://stripo.email/">
                    ${this.api.translate('Buy')}
                </a>
            </td>
        `
    }

    onCreated(node) {
        const eventId = '1234-56';
        this.api.getDocumentModifier()
            .modifyHtml(node)
            .setAttribute('event-id', eventId)
            .apply(new ModificationDescription('Set event-id {eventId}').withParams({ eventId: eventId }));
    }

    // Additional block configuration methods...
}

export default new ExtensionBuilder()
    .withLocalization({
        'uk': uk,
    })
    .addBlock(SimpleBlock)
    .build();

Custom Font Management

Dynamically add custom fonts to the editor:

javascript
import {Block} from '@stripoinc/ui-editor-extensions';

class SimpleBlock extends Block {
  onCreated(node) {
    // Add a Google Font
    this.api.addCustomFont({
      name: 'Roboto Slab',
      fontFamily: 'Roboto Slab, serif',
      url: 'https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;700'
    });
  }

  // Additional block configuration methods...
}

Editor State Management

Monitor and respond to editor state changes:

javascript
import {Block, EditorStatePropertyType, PreviewDeviceMode} from '@stripoinc/ui-editor-extensions';

class SimpleBlock extends Block {
  onCreated(node) {
      // Get current editor state
      const state = this.api.getEditorState();
      console.log('Current device:', state.previewDeviceMode);
      console.log('Panel position:', state.panelPosition);

      // Subscribe to device mode changes
      this.api.onEditorStatePropUpdated(
          EditorStatePropertyType.previewDeviceMode,
          (newMode, oldMode) => {
              if (newMode === PreviewDeviceMode.MOBILE) {
                  console.log('Switching to mobile view');
              } else {
                  console.log('Switching to desktop view');
              }
          }
      );
  }

  // Additional block configuration methods...
}

Click Outside Behavior

Control how the editor handles clicks outside of blocks. This is particularly useful for custom toolbars and popup windows:

javascript
import {Block, EditorStatePropertyType, PreviewDeviceMode} from '@stripoinc/ui-editor-extensions';

class SimpleBlock extends Block {
    onSelect(node) {
        // Prevent deselection when clicking outside
        this.api.ignoreClickOutside(true);

        // Show custom toolbar
        this.showCustomToolbar();
    }

    showCustomToolbar() {
        const toolbar = this.createToolbar();
        document.body.appendChild(toolbar);

        // Re-enable normal behavior when done
        toolbar.addEventListener('close', () => {
            this.api.ignoreClickOutside(false);
            toolbar.remove();
        });
    }

  // Additional block configuration methods...
}

AI and Emoji Popovers

Open the default AI assistant and emoji picker popovers:

javascript
import {ExtensionPopoverType, PopoverSide, UIElement} from '@stripoinc/ui-editor-extensions';

class SimplePopoverUIElement extends UIElement {
    getId() {
        return 'popovers-example';
    }
    
    getTemplate() {
        return `
            <div>
                <button class="emoji-button">Pick Emoji</button>
                <button class="ai-button">Improve with AI</button>
            </div>`
    }

    onRender(container) {
        this.emojiButton = container.querySelector('.emoji-button');
        this.aiButton = container.querySelector('.ai-button');
        this.emojiButton.addEventListener('click', this.showEmojiPopover.bind(this));
        this.aiButton.addEventListener('click', this.showAiPopover.bind(this));
    }

    showEmojiPopover() {
        this.api.openEmojiPopover({
            targetElement: this.emojiButton,
            preferredSides: [PopoverSide.LEFT],
            onResult: (result) => { console.log(result); }
        })
    }

    showAiPopover() {
        this.api.openAIPopover({
            targetElement: this.aiButton,
            value: 'Hello world',
            preferredSides: [PopoverSide.LEFT],
            type: ExtensionPopoverType.AI_TEXT,
            onResult: (result) => { console.log(result); }
        })
    }

    onDestroy() {
        this.emojiButton.removeEventListener('click', this.showEmojiPopover.bind(this));
        this.aiButton.removeEventListener('click', this.showAiPopover.bind(this));
    }
}

Document Root Access

Access and traverse the document structure:

javascript
import {Block} from '@stripoinc/ui-editor-extensions';

class SimpleBlock extends Block {
    onDocumentInit() {
        const linksCount = this.api.getDocumentRootHtmlNode()
            .querySelectorAll(`a`).length;
        
        const h1FontFamily = this.api.getDocumentRootCssNode()
            .querySelector('h1 {font-family}').getAttributeValue();
    }

    // Additional block configuration methods...
}

Modification API Usage

Use the Template Modification System to make template changes:

javascript
const modifier = this.api.getDocumentModifier();

Block API Usage

View-Only Mode

Control the block's state. In view-only mode, the block cannot be added to the template via drag and drop, but can still be edited using the editor's UI:

javascript
import {Block} from '@stripoinc/ui-editor-extensions';

class SimpleBlock extends Block {
    onDocumentInit() {
        const blocks = this.api.getDocumentRoot()
            .querySelectorAll(`.${this.getUniqueBlockClassname()}`);

        this.api.setViewOnly(!!blocks.length);
    }

    // Additional block configuration methods...
}

Control API Usage

Managing UI Element Values

Control and synchronize UI element values using the following methods:

  • this.api.getValues - Retrieve current values
  • this.api.updateValues - Update multiple values at once
  • this.api.onValueChanged - Listen for value changes
  • this.api.setVisibility - Show/hide UI elements
  • this.api.setUIEAttribute - Set UI element attributes
javascript
import {Control, UEAttr, UIElementType} from '@stripoinc/ui-editor-extensions';

export class AdvancedControl extends Control {
    getId() {
        return 'advanced-control';
    }

    getTemplate() {
        return `
            <div class="container two-columns">
                <${UIElementType.LABEL} ${UEAttr.LABEL.text}="Settings:"></${UIElementType.LABEL}>
                <${UIElementType.SWITCHER} ${UEAttr.SWITCHER.name}="enableFeature"></${UIElementType.SWITCHER}>
            </div>
            <div>
                 <${UIElementType.COUNTER} 
                    ${UEAttr.COUNTER.name}="itemCount" 
                    ${UEAttr.COUNTER.minValue}="1"
                    ${UEAttr.COUNTER.maxValue}="10"
                    ${UEAttr.COUNTER.step}="1"></${UIElementType.COUNTER}>
                
                <${UIElementType.SELECTPICKER} ${UEAttr.SELECTPICKER.name}="styleSelect" style="float: right">
                    <${UIElementType.SELECT_ITEM} ${UEAttr.SELECT_ITEM.value}="modern" ${UEAttr.SELECT_ITEM.text}="Modern"></${UIElementType.SELECT_ITEM}>
                    <${UIElementType.SELECT_ITEM} ${UEAttr.SELECT_ITEM.value}="classic" ${UEAttr.SELECT_ITEM.text}="Classic"></${UIElementType.SELECT_ITEM}>
                </${UIElementType.SELECTPICKER}>
            </div>`;
    }

    onRender() {
        // Set initial values for all UI elements
        this.api.updateValues({
            'enableFeature': true,
            'itemCount': 5,
            'styleSelect': 'modern'
        });

        // Listen to individual value changes
        this.api.onValueChanged('enableFeature', (enabled, wasEnabled) => {
            // Show/hide related controls based on toggle
            this.api.setVisibility('itemCount', enabled);
            this.api.setVisibility('styleSelect', enabled);

            if (enabled) {
                this.getAllValues(); // Log current values
            }
        });

        this.api.onValueChanged('styleSelect', (newValue, oldValue) => {
            // Set counter max value based on selected style
            const maxValue = newValue === 'modern' ? 10 : 20;
            this.api.setUIEAttribute('itemCount', UEAttr.COUNTER.maxValue, maxValue);
        });
    }

    getAllValues() {
        // Get all current values at once
        const values = this.api.getValues();
        console.log('Current control state:', values);
        return values;
    }
}

UI Element API

The UI Element API provides methods for custom UI components.

Value Change Notification

Notify the editor when UI element values change:

javascript
import {UIElement} from '@stripoinc/ui-editor-extensions';

export class CustomSlider extends UIElement {
    getId() {
        return 'custom-slider';
    }

    getTemplate() {
        return `
          <div class="custom-slider-container">
            <input type="range" class="slider" min="0" max="100" value="50">
            <span class="value-display">50</span>
          </div>
        `;
    }

    onRender(container) {
        this.slider = container.querySelector('.slider');
        this.display = container.querySelector('.value-display');

        this.slider.addEventListener('input', (event) => {
            const value = parseInt(event.target.value);
            this.display.textContent = value;

            // Notify the editor of the value change
            this.api.onValueChanged(value);
        });
    }

    getValue() {
        return parseInt(this.slider.value);
    }

    setValue(value) {
        this.slider.value = value;
        this.display.textContent = value;
    }
}