Custom Tools
Register your own drag-and-drop content tools with custom properties, icons, and HTML renderers.
- React
- Vue
- Angular
- Vanilla JS
import { useRef } from 'react';
import { PexelizeEditor, PexelizeEditorRef } from '@pexelize/react-editor';
import type { PexelizeToolConfig } from '@pexelize/editor-types';
const testimonialTool: PexelizeToolConfig = {
name: 'testimonial',
label: 'Testimonial',
icon: 'https://cdn.example.com/icons/testimonial.svg',
position: 10,
properties: {
quote: { label: 'Quote', type: 'richtext', value: 'This product changed everything.' },
authorName: { label: 'Author Name', type: 'text', value: 'Jane Doe' },
authorTitle: { label: 'Author Title', type: 'text', value: 'CEO, Acme Inc.' },
avatarUrl: { label: 'Avatar', type: 'image', value: '' },
starRating: { label: 'Stars', type: 'select', value: '5', options: ['1','2','3','4','5'] },
},
renderer: (values) => `
<div style="padding:24px;background:#f9fafb;border-left:4px solid #6366f1;border-radius:8px;">
<p style="font-style:italic;font-size:16px;">"${values.quote}"</p>
<div style="display:flex;align-items:center;margin-top:12px;">
${values.avatarUrl ? `<img src="${values.avatarUrl}" width="40" height="40" style="border-radius:50%;margin-right:12px;" />` : ''}
<div>
<strong>${values.authorName}</strong>
<br/><span style="color:#6b7280;font-size:13px;">${values.authorTitle}</span>
</div>
</div>
<div style="margin-top:8px;">${'★'.repeat(Number(values.starRating))}${'☆'.repeat(5 - Number(values.starRating))}</div>
</div>
`,
};
function EditorWithTestimonial() {
const editorRef = useRef<PexelizeEditorRef>(null);
const handleReady = () => {
editorRef.current?.editor?.registerTool(testimonialTool);
};
return (
<PexelizeEditor
ref={editorRef}
editorKey="pk_your_key"
editorMode="email"
onReady={handleReady}
/>
);
}
<template>
<PexelizeEditor
ref="editorRef"
editor-key="pk_your_key"
editor-mode="email"
@ready="onReady"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { PexelizeEditor } from '@pexelize/vue-editor';
import type { PexelizeToolConfig } from '@pexelize/editor-types';
const editorRef = ref<InstanceType<typeof PexelizeEditor>>();
const testimonialTool: PexelizeToolConfig = {
name: 'testimonial',
label: 'Testimonial',
icon: 'https://cdn.example.com/icons/testimonial.svg',
position: 10,
properties: {
quote: { label: 'Quote', type: 'richtext', value: 'This product changed everything.' },
authorName: { label: 'Author Name', type: 'text', value: 'Jane Doe' },
authorTitle: { label: 'Author Title', type: 'text', value: 'CEO, Acme Inc.' },
},
renderer: (values) => `
<div style="padding:24px;background:#f9fafb;border-left:4px solid #6366f1;">
<p style="font-style:italic;">"${values.quote}"</p>
<strong>${values.authorName}</strong><br/>
<span style="color:#6b7280;">${values.authorTitle}</span>
</div>
`,
};
function onReady() {
editorRef.value?.registerTool(testimonialTool);
}
</script>
import { Component, ViewChild } from '@angular/core';
import { PexelizeEditorComponent } from '@pexelize/angular-editor';
import type { PexelizeSDK, PexelizeToolConfig } from '@pexelize/editor-types';
@Component({
selector: 'app-custom-tool',
standalone: true,
imports: [PexelizeEditorComponent],
template: `
<pexelize-editor
#editor
editorKey="pk_your_key"
editorMode="email"
(ready)="onReady($event)"
></pexelize-editor>
`,
})
export class CustomToolComponent {
@ViewChild('editor') editorComp!: PexelizeEditorComponent;
private sdk: PexelizeSDK | null = null;
onReady(sdk: PexelizeSDK) {
this.sdk = sdk;
this.sdk.registerTool({
name: 'testimonial',
label: 'Testimonial',
icon: 'https://cdn.example.com/icons/testimonial.svg',
position: 10,
properties: {
quote: { label: 'Quote', type: 'richtext', value: 'This product changed everything.' },
authorName: { label: 'Author Name', type: 'text', value: 'Jane Doe' },
},
renderer: (values) => `
<div style="padding:24px;background:#f9fafb;border-left:4px solid #6366f1;">
<p style="font-style:italic;">"${values.quote}"</p>
<strong>${values.authorName}</strong>
</div>
`,
});
}
}
pexelize.init({
containerId: 'editor-container',
editorKey: 'pk_your_key',
editorMode: 'email',
callbacks: {
onReady: () => {
pexelize.registerTool({
name: 'testimonial',
label: 'Testimonial',
icon: 'https://cdn.example.com/icons/testimonial.svg',
position: 10,
properties: {
quote: { label: 'Quote', type: 'richtext', value: 'This product changed everything.' },
authorName: { label: 'Author Name', type: 'text', value: 'Jane Doe' },
authorTitle: { label: 'Author Title', type: 'text', value: 'CEO, Acme Inc.' },
},
renderer: (values) => `
<div style="padding:24px;background:#f9fafb;border-left:4px solid #6366f1;">
<p style="font-style:italic;">"${values.quote}"</p>
<strong>${values.authorName}</strong><br/>
<span style="color:#6b7280;">${values.authorTitle}</span>
</div>
`,
});
},
},
});
Register tools after
onReadyCustom tools must be registered after the editor has initialized. Always call registerTool() inside the onReady callback.
Property types
Each property in the properties object configures one field in the tool's settings panel:
| Type | Description | Example value |
|---|---|---|
text | Single-line text input | 'Jane Doe' |
richtext | Rich text editor with formatting | '<b>Hello</b> world' |
image | Image picker (opens file manager) | 'https://...' |
color | Color picker | '#6366f1' |
select | Dropdown select | '5' (with options array) |
toggle | Boolean toggle switch | true |
number | Numeric input with optional min/max | 24 |
alignment | Horizontal alignment picker | 'center' |
Unregister a custom tool
Remove a previously registered tool by name:
pexelize.unregisterTool('testimonial');
Design compatibility
Designs saved with a custom tool will show a placeholder if that tool is not registered when the design is loaded. Always register custom tools before calling loadDesign().
PexelizeToolConfig reference
interface PexelizeToolConfig {
name: string; // Unique identifier
label: string; // Display name in the tool panel
icon: string; // URL to an SVG or PNG icon
position?: number; // Order in the tool panel
properties: Record<string, {
label: string;
type: 'text' | 'richtext' | 'image' | 'color' | 'select' | 'toggle' | 'number' | 'alignment';
value: unknown; // Default value
options?: string[]; // For 'select' type only
editable?: boolean; // Lock the property (default: true)
}>;
renderer: (values: Record<string, unknown>) => string; // Returns HTML
}
Method reference
| Method | Returns | Description |
|---|---|---|
registerTool(config) | void | Register a custom drag-and-drop tool |
unregisterTool(name) | void | Remove a registered custom tool |
Next steps
- Configure Tools — enable, disable, and reorder built-in tools
- Modules — save tool combinations as reusable content blocks
- Merge Tags — insert dynamic personalization tokens