or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcustomization.mdindex.mdui-management.mdupload.md
tile.json

customization.mddocs/

Customization and Tunes

Visual customization and tune system for @editorjs/image providing borders, backgrounds, stretching, captions, and custom actions with full UI state management.

Capabilities

Built-in Tunes System

Core tune system providing standard image customization options with toggle functionality and visual state management.

static get tunes(): Array<ActionConfig> {
  return [
    {
      name: 'withBorder',
      icon: IconAddBorder,
      title: 'With border',
      toggle: true,
    },
    {
      name: 'stretched',
      icon: IconStretch,
      title: 'Stretch image',
      toggle: true,
    },
    {
      name: 'withBackground',
      icon: IconAddBackground,
      title: 'With background',
      toggle: true,
    },
  ];
}

interface ActionConfig {
  /** Unique identifier for the action/tune */
  name: string;
  /** SVG icon string to display in settings menu */
  icon: string;
  /** Human-readable title for the action/tune */
  title: string;
  /** Whether this action is a toggle button (true) or single-action button (false) */
  toggle?: boolean;
  /** Custom function to execute when action is triggered, receives action name as parameter */
  action?: (actionName: string) => void;
}

Usage Examples:

// Built-in tunes are automatically available
// Users can toggle these options in the settings menu:

// 1. Border tune - adds border around image
// 2. Stretch tune - stretches image to full container width
// 3. Background tune - adds background color behind image

// Data structure includes tune states
interface ImageToolData {
  withBorder: boolean;    // Border tune state
  stretched: boolean;     // Stretch tune state  
  withBackground: boolean; // Background tune state
  caption: string;
  file: { url: string };
}

Tune Settings Rendering

Dynamic settings menu generation with tune activation handling and state management.

/**
 * Generate configuration for block tunes settings menu
 * Combines built-in tunes with custom actions
 * @returns Configuration for Editor.js tune menu
 */
renderSettings(): TunesMenuConfig;

interface TunesMenuConfig {
  icon: string;
  label: string;
  name: string;
  toggle?: boolean;
  isActive: boolean;
  onActivate: () => void;
}

Usage Examples:

// Settings menu automatically includes:
class ImageTool {
  renderSettings(): TunesMenuConfig {
    const allTunes = [
      ...ImageTool.tunes,           // Built-in tunes
      ...(this.config.actions || []) // Custom actions
    ];
    
    // Filter based on feature configuration
    const availableTunes = allTunes.filter(tune => {
      return isFeatureEnabled(tune.name);
    });
    
    return availableTunes.map(tune => ({
      icon: tune.icon,
      label: this.api.i18n.t(tune.title),
      name: tune.name,
      toggle: tune.toggle,
      isActive: this.getTuneState(tune.name),
      onActivate: () => this.handleTuneToggle(tune)
    }));
  }
}

Caption Management

Comprehensive caption system with optional toggle functionality and placeholder customization.

interface CaptionConfig {
  captionPlaceholder?: string;
  features?: {
    caption?: boolean | 'optional';
  };
}

/**
 * Handle caption tune toggling and state management
 * @param tuneName - Name of the tune being toggled
 * @param state - New state for the tune
 */
private tuneToggled(tuneName: keyof ImageToolData, state: boolean): void;

Usage Examples:

// Always enabled captions (default)
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        captionPlaceholder: 'Enter image description...'
      }
    }
  }
});

// Optional captions (user can toggle)
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          caption: 'optional'  // Adds caption toggle in settings
        },
        captionPlaceholder: 'Add a caption...'
      }
    }
  }
});

// Disabled captions
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          caption: false  // No caption functionality
        }
      }
    }
  }
});

Custom Actions

Extensible action system allowing addition of custom tunes with custom behavior and UI integration.

interface CustomActionConfig extends ActionConfig {
  name: string;
  icon: string;
  title: string;
  toggle?: boolean;
  action?: (actionName: string) => void;
}

interface ImageConfig {
  actions?: ActionConfig[];
}

Usage Examples:

// Adding custom actions
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        actions: [
          {
            name: 'rotate',
            icon: `<svg viewBox="0 0 24 24">
              <path d="M7.11 8.53L5.7 7.11C4.8 8.27 4.24 9.61 4.07 11h2.02c.14-.87.49-1.72 1.02-2.47zM6.09 13H4.07c.17 1.39.72 2.73 1.62 3.89l1.41-1.42c-.52-.75-.87-1.59-1.01-2.47zm1.01 5.32c1.16.9 2.51 1.44 3.9 1.61V17.9c-.87-.15-1.71-.49-2.46-1.03L7.1 18.32zM13 4.07V1L8.45 5.55 13 10V6.09c2.84.48 5 2.94 5 5.91s-2.16 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93s-3.05-7.44-7-7.93z"/>
            </svg>`,
            title: 'Rotate Image',
            action: (actionName) => {
              // Custom rotation logic
              const imageEl = document.querySelector('.image-tool__image-picture');
              if (imageEl) {
                const currentRotation = imageEl.dataset.rotation || '0';
                const newRotation = (parseInt(currentRotation) + 90) % 360;
                imageEl.style.transform = `rotate(${newRotation}deg)`;
                imageEl.dataset.rotation = newRotation.toString();
              }
            }
          },
          {
            name: 'filters',
            icon: `<svg viewBox="0 0 24 24">
              <path d="M9.5,3C13.09,3 16,5.91 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16C5.91,16 3,13.09 3,9.5C3,5.91 5.91,3 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"/>
            </svg>`,
            title: 'Apply Filters',
            toggle: true,
            action: (actionName) => {
              // Toggle filter modal or panel
              openFilterPanel();
            }
          },
          {
            name: 'alt-text',
            icon: `<svg viewBox="0 0 24 24">
              <path d="M9,7H11L13,15H11L10.5,13H7.5L7,15H5L7,7M8,9L7.8,11H9.2L9,9M14,17V15H21V17H14M14,13V11H21V13H14M14,9V7H21V9H14Z"/>
            </svg>`,
            title: 'Add Alt Text',
            action: (actionName) => {
              // Open alt text input dialog
              const altText = prompt('Enter alt text for accessibility:');
              if (altText) {
                const imageEl = document.querySelector('.image-tool__image-picture');
                if (imageEl) {
                  imageEl.setAttribute('alt', altText);
                }
              }
            }
          }
        ]
      }
    }
  }
});

Feature Toggle System

Granular control over available features and tunes with configuration-based enabling/disabling.

interface FeaturesConfig {
  /** Enable/disable background tune (default: true) */
  background?: boolean;
  /** Enable/disable border tune (default: true) */
  border?: boolean;
  /** Enable/disable caption: true=always visible, false=disabled, 'optional'=user toggleable (default: true) */
  caption?: boolean | 'optional';
  /** Enable/disable stretch tune (default: true) */
  stretch?: boolean;
}

/**
 * Generate settings menu filtering tunes based on feature configuration
 * Combines built-in tunes with custom actions and applies feature filters
 * @returns Configuration for Editor.js tune menu
 */
renderSettings(): TunesMenuConfig;

Usage Examples:

// Selective feature enabling
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          border: true,         // Enable border tune
          background: false,    // Disable background tune
          stretch: true,        // Enable stretch tune
          caption: 'optional'   // Make caption optional
        }
      }
    }
  }
});

// Minimal feature set
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          border: false,
          background: false,
          stretch: false,
          caption: false
        }
      }
    }
  }
});

// Maximum features (default behavior)
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ }
        // All features enabled by default
      }
    }
  }
});

UI State Management

Comprehensive UI state management system handling visual representation of tune states and user interactions.

/**
 * Apply visual representation of activated tune
 * @param tuneName - Name of the tune to apply
 * @param status - Enable or disable state
 */
applyTune(tuneName: string, status: boolean): void;

/**
 * Set tune state and update UI accordingly
 * @param tuneName - Name of the tune to set
 * @param value - New state value
 */
private setTune(tuneName: keyof ImageToolData, value: boolean): void;

enum UiState {
  Empty = 'empty',
  Uploading = 'uploading',
  Filled = 'filled'
}

Usage Examples:

// UI classes applied automatically based on tune states:

// Border tune active
// .image-tool--withBorder

// Stretched tune active  
// .image-tool--stretched

// Background tune active
// .image-tool--withBackground

// Caption tune active
// .image-tool--caption

// Multiple tunes can be active simultaneously
// .image-tool--withBorder.image-tool--stretched.image-tool--withBackground

// CSS styling examples
.image-tool--withBorder .image-tool__image-picture {
  border: 2px solid #e6e9ec;
  border-radius: 3px;
}

.image-tool--withBackground .image-tool__image {
  background: #f8f9fa;
  padding: 15px;
}

.image-tool--stretched {
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

.image-tool--caption .image-tool__caption {
  display: block;
}

Data State Management

Comprehensive data state management preserving tune states and handling data validation with type safety.

interface ImageToolData<Actions = {}, AdditionalFileData = {}> {
  caption: string;
  withBorder: boolean;
  withBackground: boolean;
  stretched: boolean;
  file: {
    url: string;
  } & AdditionalFileData;
} & (Actions extends Record<string, boolean> ? Actions : {});

/**
 * Save current block data including all tune states
 * @returns Complete image tool data
 */
save(): ImageToolData;

/**
 * Validate saved data ensuring required fields are present
 * @param savedData - Data to validate
 * @returns Validation result
 */
validate(savedData: ImageToolData): boolean;

Usage Examples:

// Saved data structure includes all tune states
{
  "caption": "Beautiful sunset over the mountains",
  "withBorder": true,
  "withBackground": false,
  "stretched": true,
  "file": {
    "url": "https://cdn.example.com/sunset.jpg",
    "dimensions": {
      "width": 1920,
      "height": 1080
    }
  }
}

// Data restoration automatically applies tune states
class ImageTool {
  constructor({ data }) {
    // Restore tune states from saved data
    this.data = {
      caption: data.caption || '',
      withBorder: data.withBorder || false,
      withBackground: data.withBackground || false,
      stretched: data.stretched || false,
      file: data.file || { url: '' }
    };
    
    // Apply UI states based on data
    this.applyTunesFromData();
  }
}